diff options
-rw-r--r-- | drivers/staging/at76_usb/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/at76_usb/at76_usb.c | 4614 | ||||
-rw-r--r-- | drivers/staging/at76_usb/at76_usb.h | 227 |
3 files changed, 3878 insertions, 965 deletions
diff --git a/drivers/staging/at76_usb/Kconfig b/drivers/staging/at76_usb/Kconfig index 4c0e55e1544..8606f962162 100644 --- a/drivers/staging/at76_usb/Kconfig +++ b/drivers/staging/at76_usb/Kconfig @@ -1,6 +1,6 @@ config USB_ATMEL tristate "Atmel at76c503/at76c505/at76c505a USB cards" - depends on MAC80211 && WLAN_80211 && USB + depends on WLAN_80211 && USB default N select FW_LOADER ---help--- diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c index 185533e5476..9195ee9319f 100644 --- a/drivers/staging/at76_usb/at76_usb.c +++ b/drivers/staging/at76_usb/at76_usb.c @@ -6,7 +6,6 @@ * Copyright (c) 2004 Nick Jones * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com> * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org> - * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -17,13 +16,6 @@ * Atmel AT76C503A/505/505A. * * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed - * - * TODO for the mac80211 port: - * o adhoc support - * o RTS/CTS support - * o Power Save Mode support - * o support for short/long preambles - * o export variables through debugfs/sysfs */ #include <linux/init.h> @@ -44,7 +36,7 @@ #include <net/ieee80211_radiotap.h> #include <linux/firmware.h> #include <linux/leds.h> -#include <net/mac80211.h> +#include <net/ieee80211.h> #include "at76_usb.h" @@ -84,43 +76,31 @@ #define DBG_WE_EVENTS 0x08000000 /* dump wireless events */ #define DBG_FW 0x10000000 /* firmware download */ #define DBG_DFU 0x20000000 /* device firmware upgrade */ -#define DBG_CMD 0x40000000 -#define DBG_MAC80211 0x80000000 #define DBG_DEFAULTS 0 /* Use our own dbg macro */ #define at76_dbg(bits, format, arg...) \ -do { \ - if (at76_debug & (bits)) \ - printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \ -} while (0) - -#define at76_dbg_dump(bits, buf, len, format, arg...) \ -do { \ - if (at76_debug & (bits)) { \ + do { \ + if (at76_debug & (bits)) \ printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \ - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); \ - } \ -} while (0) + } while (0) static int at76_debug = DBG_DEFAULTS; -#define FIRMWARE_IS_WPA(ver) ((ver.major == 1) && (ver.minor == 103)) - /* Protect against concurrent firmware loading and parsing */ static struct mutex fw_mutex; static struct fwentry firmwares[] = { - [0] = { "" }, - [BOARD_503_ISL3861] = { "atmel_at76c503-i3861.bin" }, - [BOARD_503_ISL3863] = { "atmel_at76c503-i3863.bin" }, - [BOARD_503] = { "atmel_at76c503-rfmd.bin" }, - [BOARD_503_ACC] = { "atmel_at76c503-rfmd-acc.bin" }, - [BOARD_505] = { "atmel_at76c505-rfmd.bin" }, - [BOARD_505_2958] = { "atmel_at76c505-rfmd2958.bin" }, - [BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" }, - [BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" }, + [0] = {""}, + [BOARD_503_ISL3861] = {"atmel_at76c503-i3861.bin"}, + [BOARD_503_ISL3863] = {"atmel_at76c503-i3863.bin"}, + [BOARD_503] = {"atmel_at76c503-rfmd.bin"}, + [BOARD_503_ACC] = {"atmel_at76c503-rfmd-acc.bin"}, + [BOARD_505] = {"atmel_at76c505-rfmd.bin"}, + [BOARD_505_2958] = {"atmel_at76c505-rfmd2958.bin"}, + [BOARD_505A] = {"atmel_at76c505a-rfmd2958.bin"}, + [BOARD_505AMX] = {"atmel_at76c505amx-rfmd.bin"}, }; #define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops) @@ -130,133 +110,133 @@ static struct usb_device_id dev_table[] = { * at76c503-i3861 */ /* Generic AT76C503/3861 device */ - { USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Linksys WUSB11 v2.1/v2.6 */ - { USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Netgear MA101 rev. A */ - { USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Tekram U300C / Allnet ALL0193 */ - { USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* HP HN210W J7801A */ - { USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Sitecom/Z-Com/Zyxel M4Y-750 */ - { USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Dynalink/Askey WLL013 (intersil) */ - { USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */ - { USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* BenQ AWL300 */ - { USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Addtron AWU-120, Compex WLU11 */ - { USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Intel AP310 AnyPoint II USB */ - { USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Dynalink L11U */ - { USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* Arescom WL-210, FCC id 07J-GL2411USB */ - { USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* I-O DATA WN-B11/USB */ - { USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* BT Voyager 1010 */ - { USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861) }, + {USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861)}, /* * at76c503-i3863 */ /* Generic AT76C503/3863 device */ - { USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863) }, + {USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863)}, /* Samsung SWL-2100U */ - { USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863) }, + {USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863)}, /* * at76c503-rfmd */ /* Generic AT76C503/RFMD device */ - { USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503)}, /* Dynalink/Askey WLL013 (rfmd) */ - { USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503)}, /* Linksys WUSB11 v2.6 */ - { USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503)}, /* Network Everywhere NWU11B */ - { USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503)}, /* Netgear MA101 rev. B */ - { USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503)}, /* D-Link DWL-120 rev. E */ - { USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503)}, /* Actiontec 802UAT1, HWU01150-01UK */ - { USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503)}, /* AirVast W-Buddie WN210 */ - { USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503)}, /* Dick Smith Electronics XH1153 802.11b USB adapter */ - { USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503)}, /* CNet CNUSB611 */ - { USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503)}, /* FiberLine FL-WL200U */ - { USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503)}, /* BenQ AWL400 USB stick */ - { USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503)}, /* 3Com 3CRSHEW696 */ - { USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503)}, /* Siemens Santis ADSL WLAN USB adapter WLL 013 */ - { USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503)}, /* Belkin F5D6050, version 2 */ - { USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503)}, /* iBlitzz, BWU613 (not *B or *SB) */ - { USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503)}, /* Gigabyte GN-WLBM101 */ - { USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503)}, /* Planex GW-US11S */ - { USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503)}, /* Internal WLAN adapter in h5[4,5]xx series iPAQs */ - { USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503)}, /* Corega Wireless LAN USB-11 mini */ - { USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503)}, /* Corega Wireless LAN USB-11 mini2 */ - { USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503)}, /* Uniden PCW100 */ - { USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503) }, + {USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503)}, /* * at76c503-rfmd-acc */ /* SMC2664W */ - { USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC) }, + {USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC)}, /* Belkin F5D6050, SMC2662W v2, SMC2662W-AR */ - { USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC) }, + {USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC)}, /* * at76c505-rfmd */ /* Generic AT76C505/RFMD */ - { USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505) }, + {USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505)}, /* * at76c505-rfmd2958 */ /* Generic AT76C505/RFMD, OvisLink WL-1130USB */ - { USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)}, /* Fiberline FL-WL240U */ - { USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958)}, /* CNet CNUSB-611G */ - { USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958)}, /* Linksys WUSB11 v2.8 */ - { USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958)}, /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */ - { USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958)}, /* Corega WLAN USB Stick 11 */ - { USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)}, /* Microstar MSI Box MS6978 */ - { USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) }, + {USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958)}, /* * at76c505a-rfmd2958 */ /* Generic AT76C505A device */ - { USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A) }, + {USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A)}, /* Generic AT76C505AS device */ - { USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) }, + {USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A)}, /* Siemens Gigaset USB WLAN Adapter 11 */ - { USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) }, + {USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A)}, /* * at76c505amx-rfmd */ /* Generic AT76C505AMX device */ - { USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX) }, - { } + {USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX)}, + {} }; MODULE_DEVICE_TABLE(usb, dev_table); @@ -264,8 +244,26 @@ MODULE_DEVICE_TABLE(usb, dev_table); /* Supported rates of this hardware, bit 7 marks basic rates */ static const u8 hw_rates[] = { 0x82, 0x84, 0x0b, 0x16 }; +/* Frequency of each channel in MHz */ +static const long channel_frequency[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + +#define NUM_CHANNELS ARRAY_SIZE(channel_frequency) + static const char *const preambles[] = { "long", "short", "auto" }; +static const char *const mac_states[] = { + [MAC_INIT] = "INIT", + [MAC_SCANNING] = "SCANNING", + [MAC_AUTH] = "AUTH", + [MAC_ASSOC] = "ASSOC", + [MAC_JOINING] = "JOINING", + [MAC_CONNECTED] = "CONNECTED", + [MAC_OWN_IBSS] = "OWN_IBSS" +}; + /* Firmware download */ /* DFU states */ #define STATE_IDLE 0x00 @@ -300,30 +298,17 @@ struct dfu_status { static inline int at76_is_intersil(enum board_type board) { - if (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863) - return 1; - return 0; + return (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863); } static inline int at76_is_503rfmd(enum board_type board) { - if (board == BOARD_503 || board == BOARD_503_ACC) - return 1; - return 0; -} - -static inline int at76_is_505(enum board_type board) -{ - if (board == BOARD_505 || board == BOARD_505_2958) - return 1; - return 0; + return (board == BOARD_503 || board == BOARD_503_ACC); } static inline int at76_is_505a(enum board_type board) { - if (board == BOARD_505A || board == BOARD_505AMX) - return 1; - return 0; + return (board == BOARD_505A || board == BOARD_505AMX); } /* Load a block of the first (internal) part of the firmware */ @@ -504,6 +489,41 @@ exit: return ret; } +/* Report that the scan results are ready */ +static inline void at76_iwevent_scan_complete(struct net_device *netdev) +{ + union iwreq_data wrqu; + wrqu.data.length = 0; + wrqu.data.flags = 0; + wireless_send_event(netdev, SIOCGIWSCAN, &wrqu, NULL); + at76_dbg(DBG_WE_EVENTS, "%s: SIOCGIWSCAN sent", netdev->name); +} + +static inline void at76_iwevent_bss_connect(struct net_device *netdev, + u8 *bssid) +{ + union iwreq_data wrqu; + wrqu.data.length = 0; + wrqu.data.flags = 0; + memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL); + at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name, + __func__); +} + +static inline void at76_iwevent_bss_disconnect(struct net_device *netdev) +{ + union iwreq_data wrqu; + wrqu.data.length = 0; + wrqu.data.flags = 0; + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL); + at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name, + __func__); +} + #define HEX2STR_BUFFERS 4 #define HEX2STR_MAX_LEN 64 #define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10) @@ -575,6 +595,37 @@ static void at76_ledtrig_tx_activity(void) mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4); } +/* Check if the given ssid is hidden */ +static inline int at76_is_hidden_ssid(u8 *ssid, int length) +{ + static const u8 zeros[32]; + + if (length == 0) + return 1; + + if (length == 1 && ssid[0] == ' ') + return 1; + + return (memcmp(ssid, zeros, length) == 0); +} + +static inline void at76_free_bss_list(struct at76_priv *priv) +{ + struct list_head *next, *ptr; + unsigned long flags; + + spin_lock_irqsave(&priv->bss_list_spinlock, flags); + + priv->curr_bss = NULL; + + list_for_each_safe(ptr, next, &priv->bss_list) { + list_del(ptr); + kfree(list_entry(ptr, struct bss_info, list)); + } + + spin_unlock_irqrestore(&priv->bss_list_spinlock, flags); +} + static int at76_remap(struct usb_device *udev) { int ret; @@ -676,7 +727,7 @@ exit: kfree(hwcfg); if (ret < 0) printk(KERN_ERR "%s: cannot get HW Config (error %d)\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); return ret; } @@ -685,15 +736,15 @@ static struct reg_domain const *at76_get_reg_domain(u16 code) { int i; static struct reg_domain const fd_tab[] = { - { 0x10, "FCC (USA)", 0x7ff }, /* ch 1-11 */ - { 0x20, "IC (Canada)", 0x7ff }, /* ch 1-11 */ - { 0x30, "ETSI (most of Europe)", 0x1fff }, /* ch 1-13 */ - { 0x31, "Spain", 0x600 }, /* ch 10-11 */ - { 0x32, "France", 0x1e00 }, /* ch 10-13 */ - { 0x40, "MKK (Japan)", 0x2000 }, /* ch 14 */ - { 0x41, "MKK1 (Japan)", 0x3fff }, /* ch 1-14 */ - { 0x50, "Israel", 0x3fc }, /* ch 3-9 */ - { 0x00, "<unknown>", 0xffffffff } /* ch 1-32 */ + {0x10, "FCC (USA)", 0x7ff}, /* ch 1-11 */ + {0x20, "IC (Canada)", 0x7ff}, /* ch 1-11 */ + {0x30, "ETSI (most of Europe)", 0x1fff}, /* ch 1-13 */ + {0x31, "Spain", 0x600}, /* ch 10-11 */ + {0x32, "France", 0x1e00}, /* ch 10-13 */ + {0x40, "MKK (Japan)", 0x2000}, /* ch 14 */ + {0x41, "MKK1 (Japan)", 0x3fff}, /* ch 1-14 */ + {0x50, "Israel", 0x3fc}, /* ch 3-9 */ + {0x00, "<unknown>", 0xffffffff} /* ch 1-32 */ }; /* Last entry is fallback for unknown domain code */ @@ -739,24 +790,6 @@ static inline int at76_get_cmd_status(struct usb_device *udev, u8 cmd) return ret; } -#define MAKE_CMD_CASE(c) case (c): return #c - -static const char *at76_get_cmd_string(u8 cmd_status) -{ - switch (cmd_status) { - MAKE_CMD_CASE(CMD_SET_MIB); - MAKE_CMD_CASE(CMD_GET_MIB); - MAKE_CMD_CASE(CMD_SCAN); - MAKE_CMD_CASE(CMD_JOIN); - MAKE_CMD_CASE(CMD_START_IBSS); - MAKE_CMD_CASE(CMD_RADIO_ON); - MAKE_CMD_CASE(CMD_RADIO_OFF); - MAKE_CMD_CASE(CMD_STARTUP); - } - - return "UNKNOWN"; -} - static int at76_set_card_command(struct usb_device *udev, u8 cmd, void *buf, int buf_size) { @@ -772,10 +805,6 @@ static int at76_set_card_command(struct usb_device *udev, u8 cmd, void *buf, cmd_buf->size = cpu_to_le16(buf_size); memcpy(cmd_buf->data, buf, buf_size); - at76_dbg_dump(DBG_CMD, cmd_buf, sizeof(struct at76_command) + buf_size, - "issuing command %s (0x%02x)", - at76_get_cmd_string(cmd), cmd); - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, 0, 0, cmd_buf, @@ -813,13 +842,13 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd) status = at76_get_cmd_status(priv->udev, cmd); if (status < 0) { printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n", - wiphy_name(priv->hw->wiphy), status); + priv->netdev->name, status); break; } at76_dbg(DBG_WAIT_COMPLETE, "%s: Waiting on cmd %d, status = %d (%s)", - wiphy_name(priv->hw->wiphy), cmd, status, + priv->netdev->name, cmd, status, at76_get_cmd_status_string(status)); if (status != CMD_STATUS_IN_PROGRESS @@ -830,7 +859,7 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd) if (time_after(jiffies, timeout)) { printk(KERN_ERR "%s: completion timeout for command %d\n", - wiphy_name(priv->hw->wiphy), cmd); + priv->netdev->name, cmd); status = -ETIMEDOUT; break; } @@ -853,7 +882,7 @@ static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf) if (ret != CMD_STATUS_COMPLETE) { printk(KERN_INFO "%s: set_mib: at76_wait_completion failed " - "with %d\n", wiphy_name(priv->hw->wiphy), ret); + "with %d\n", priv->netdev->name, ret); ret = -EIO; } @@ -874,7 +903,7 @@ static int at76_set_radio(struct at76_priv *priv, int enable) ret = at76_set_card_command(priv->udev, cmd, NULL, 0); if (ret < 0) printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n", - wiphy_name(priv->hw->wiphy), cmd, ret); + priv->netdev->name, cmd, ret); else ret = 1; @@ -895,7 +924,44 @@ static int at76_set_pm_mode(struct at76_priv *priv) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); + + return ret; +} + +/* Set the association id for power save mode */ +static int at76_set_associd(struct at76_priv *priv, u16 id) +{ + int ret = 0; + + priv->mib_buf.type = MIB_MAC_MGMT; + priv->mib_buf.size = 2; + priv->mib_buf.index = offsetof(struct mib_mac_mgmt, station_id); + priv->mib_buf.data.word = cpu_to_le16(id); + + ret = at76_set_mib(priv, &priv->mib_buf); + if (ret < 0) + printk(KERN_ERR "%s: set_mib (associd) failed: %d\n", + priv->netdev->name, ret); + + return ret; +} + +/* Set the listen interval for power save mode */ +static int at76_set_listen_interval(struct at76_priv *priv, u16 interval) +{ + int ret = 0; + + priv->mib_buf.type = MIB_MAC; + priv->mib_buf.size = 2; + priv->mib_buf.index = offsetof(struct mib_mac, listen_interval); + priv->mib_buf.data.word = cpu_to_le16(interval); + + ret = at76_set_mib(priv, &priv->mib_buf); + if (ret < 0) + printk(KERN_ERR + "%s: set_mib (listen_interval) failed: %d\n", + priv->netdev->name, ret); return ret; } @@ -912,7 +978,7 @@ static int at76_set_preamble(struct at76_priv *priv, u8 type) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); return ret; } @@ -929,7 +995,7 @@ static int at76_set_frag(struct at76_priv *priv, u16 size) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); return ret; } @@ -946,7 +1012,7 @@ static int at76_set_rts(struct at76_priv *priv, u16 size) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) printk(KERN_ERR "%s: set_mib (rts) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); return ret; } @@ -963,41 +1029,24 @@ static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff) ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); return ret; } -static int at76_set_tkip_bssid(struct at76_priv *priv, const void *addr) +static int at76_add_mac_address(struct at76_priv *priv, void *addr) { int ret = 0; - priv->mib_buf.type = MIB_MAC_ENCRYPTION; + priv->mib_buf.type = MIB_MAC_ADDR; priv->mib_buf.size = ETH_ALEN; - priv->mib_buf.index = offsetof(struct mib_mac_encryption, tkip_bssid); + priv->mib_buf.index = offsetof(struct mib_mac_addr, mac_addr); memcpy(priv->mib_buf.data.addr, addr, ETH_ALEN); ret = at76_set_mib(priv, &priv->mib_buf); if (ret < 0) - printk(KERN_ERR "%s: set_mib (MAC_ENCRYPTION, tkip_bssid) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static int at76_reset_rsc(struct at76_priv *priv) -{ - int ret = 0; - - priv->mib_buf.type = MIB_MAC_ENCRYPTION; - priv->mib_buf.size = 4 * 8; - priv->mib_buf.index = offsetof(struct mib_mac_encryption, key_rsc); - memset(priv->mib_buf.data.data, 0 , priv->mib_buf.size); - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (MAC_ENCRYPTION, key_rsc) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + printk(KERN_ERR "%s: set_mib (MAC_ADDR, mac_addr) failed: %d\n", + priv->netdev->name, ret); return ret; } @@ -1016,16 +1065,16 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv) sizeof(struct mib_mac_addr)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x", - wiphy_name(priv->hw->wiphy), + priv->netdev->name, mac2str(m->mac_addr), m->res[0], m->res[1]); for (i = 0; i < ARRAY_SIZE(m->group_addr); i++) at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, " - "status %d", wiphy_name(priv->hw->wiphy), i, + "status %d", priv->netdev->name, i, mac2str(m->group_addr[i]), m->group_addr_status[i]); exit: kfree(m); @@ -1045,13 +1094,13 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv) sizeof(struct mib_mac_wep)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: priv_invoked %u def_key_id %u " "key_len %u excl_unencr %u wep_icv_err %u wep_excluded %u " - "encr_level %u key %d", wiphy_name(priv->hw->wiphy), + "encr_level %u key %d", priv->netdev->name, m->privacy_invoked, m->wep_default_key_id, m->wep_key_mapping_len, m->exclude_unencrypted, le32_to_cpu(m->wep_icv_error_count), @@ -1063,55 +1112,12 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv) for (i = 0; i < WEP_KEYS; i++) at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s", - wiphy_name(priv->hw->wiphy), i, + priv->netdev->name, i, hex2str(m->wep_default_keyvalue[i], key_len)); exit: kfree(m); } -static void at76_dump_mib_mac_encryption(struct at76_priv *priv) -{ - int i; - int ret; - /*int key_len;*/ - struct mib_mac_encryption *m; - - m = kmalloc(sizeof(struct mib_mac_encryption), GFP_KERNEL); - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_MAC_ENCRYPTION, m, - sizeof(struct mib_mac_encryption)); - if (ret < 0) { - dev_err(&priv->udev->dev, - "%s: at76_get_mib (MAC_ENCRYPTION) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, - "%s: MIB MAC_ENCRYPTION: tkip_bssid %s priv_invoked %u " - "ciph_key_id %u grp_key_id %u excl_unencr %u " - "ckip_key_perm %u wep_icv_err %u wep_excluded %u", - wiphy_name(priv->hw->wiphy), mac2str(m->tkip_bssid), - m->privacy_invoked, m->cipher_default_key_id, - m->cipher_default_group_key_id, m->exclude_unencrypted, - m->ckip_key_permutation, - le32_to_cpu(m->wep_icv_error_count), - le32_to_cpu(m->wep_excluded_count)); - - /*key_len = (m->encryption_level == 1) ? - WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;*/ - - for (i = 0; i < CIPHER_KEYS; i++) - at76_dbg(DBG_MIB, "%s: MIB MAC_ENCRYPTION: key %d: %s", - wiphy_name(priv->hw->wiphy), i, - hex2str(m->cipher_default_keyvalue[i], - CIPHER_KEY_LEN)); -exit: - kfree(m); -} - static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) { int ret; @@ -1125,7 +1131,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) sizeof(struct mib_mac_mgmt)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } @@ -1136,7 +1142,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) "pm_mode %d ibss_change %d res %d " "multi_domain_capability_implemented %d " "international_roaming %d country_string %.3s", - wiphy_name(priv->hw->wiphy), le16_to_cpu(m->beacon_period), + priv->netdev->name, le16_to_cpu(m->beacon_period), le16_to_cpu(m->CFP_max_duration), le16_to_cpu(m->medium_occupancy_limit), le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window), @@ -1161,7 +1167,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } @@ -1171,8 +1177,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv) "scan_type %d scan_channel %d probe_delay %u " "min_channel_time %d max_channel_time %d listen_int %d " "desired_ssid %s desired_bssid %s desired_bsstype %d", - wiphy_name(priv->hw->wiphy), - le32_to_cpu(m->max_tx_msdu_lifetime), + priv->netdev->name, le32_to_cpu(m->max_tx_msdu_lifetime), le32_to_cpu(m->max_rx_lifetime), le16_to_cpu(m->frag_threshold), le16_to_cpu(m->rts_threshold), le16_to_cpu(m->cwmin), le16_to_cpu(m->cwmax), @@ -1198,7 +1203,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } @@ -1207,7 +1212,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv) "mpdu_max_length %d cca_mode_supported %d operation_rate_set " "0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d " "phy_type %d current_reg_domain %d", - wiphy_name(priv->hw->wiphy), le32_to_cpu(m->ed_threshold), + priv->netdev->name, le32_to_cpu(m->ed_threshold), le16_to_cpu(m->slot_time), le16_to_cpu(m->sifs_time), le16_to_cpu(m->preamble_length), le16_to_cpu(m->plcp_header_length), @@ -1231,14 +1236,13 @@ static void at76_dump_mib_local(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } at76_dbg(DBG_MIB, "%s: MIB LOCAL: beacon_enable %d " "txautorate_fallback %d ssid_size %d promiscuous_mode %d " - "preamble_type %d", wiphy_name(priv->hw->wiphy), - m->beacon_enable, + "preamble_type %d", priv->netdev->name, m->beacon_enable, m->txautorate_fallback, m->ssid_size, m->promiscuous_mode, m->preamble_type); exit: @@ -1257,21 +1261,118 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv) sizeof(struct mib_mdomain)); if (ret < 0) { printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); + priv->netdev->name, ret); goto exit; } at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s", - wiphy_name(priv->hw->wiphy), + priv->netdev->name, hex2str(m->channel_list, sizeof(m->channel_list))); at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s", - wiphy_name(priv->hw->wiphy), + priv->netdev->name, hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel))); exit: kfree(m); } +static int at76_get_current_bssid(struct at76_priv *priv) +{ + int ret = 0; + struct mib_mac_mgmt *mac_mgmt = + kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL); + + if (!mac_mgmt) { + ret = -ENOMEM; + goto exit; + } + + ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, mac_mgmt, + sizeof(struct mib_mac_mgmt)); + if (ret < 0) { + printk(KERN_ERR "%s: at76_get_mib failed: %d\n", + priv->netdev->name, ret); + goto error; + } + memcpy(priv->bssid, mac_mgmt->current_bssid, ETH_ALEN); + printk(KERN_INFO "%s: using BSSID %s\n", priv->netdev->name, + mac2str(priv->bssid)); +error: + kfree(mac_mgmt); +exit: + return ret; +} + +static int at76_get_current_channel(struct at76_priv *priv) +{ + int ret = 0; + struct mib_phy *phy = kmalloc(sizeof(struct mib_phy), GFP_KERNEL); + + if (!phy) { + ret = -ENOMEM; + goto exit; + } + ret = at76_get_mib(priv->udev, MIB_PHY, phy, sizeof(struct mib_phy)); + if (ret < 0) { + printk(KERN_ERR "%s: at76_get_mib(MIB_PHY) failed: %d\n", + priv->netdev->name, ret); + goto error; + } + priv->channel = phy->channel_id; +error: + kfree(phy); +exit: + return ret; +} + +/** + * at76_start_scan - start a scan + * + * @use_essid - use the configured ESSID in non passive mode + */ +static int at76_start_scan(struct at76_priv *priv, int use_essid) +{ + struct at76_req_scan scan; + + memset(&scan, 0, sizeof(struct at76_req_scan)); + memset(scan.bssid, 0xff, ETH_ALEN); + + if (use_essid) { + memcpy(scan.essid, priv->essid, IW_ESSID_MAX_SIZE); + scan.essid_size = priv->essid_size; + } else + scan.essid_size = 0; + + /* jal: why should we start at a certain channel? we do scan the whole + range allowed by reg domain. */ + scan.channel = priv->channel; + + /* atmelwlandriver differs between scan type 0 and 1 (active/passive) + For ad-hoc mode, it uses type 0 only. */ + scan.scan_type = priv->scan_mode; + + /* INFO: For probe_delay, not multiplying by 1024 as this will be + slightly less than min_channel_time + (per spec: probe delay < min. channel time) */ + scan.min_channel_time = cpu_to_le16(priv->scan_min_time); + scan.max_channel_time = cpu_to_le16(priv->scan_max_time); + scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000); + scan.international_scan = 0; + + /* other values are set to 0 for type 0 */ + + at76_dbg(DBG_PROGRESS, "%s: start_scan (use_essid = %d, intl = %d, " + "channel = %d, probe_delay = %d, scan_min_time = %d, " + "scan_max_time = %d)", + priv->netdev->name, use_essid, + scan.international_scan, scan.channel, + le16_to_cpu(scan.probe_delay), + le16_to_cpu(scan.min_channel_time), + le16_to_cpu(scan.max_channel_time)); + + return at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan)); +} + /* Enable monitor mode */ static int at76_start_monitor(struct at76_priv *priv) { @@ -1292,6 +1393,86 @@ static int at76_start_monitor(struct at76_priv *priv) return ret; } +static int at76_start_ibss(struct at76_priv *priv) +{ + struct at76_req_ibss bss; + int ret; + + WARN_ON(priv->mac_state != MAC_OWN_IBSS); + if (priv->mac_state != MAC_OWN_IBSS) + return -EBUSY; + + memset(&bss, 0, sizeof(struct at76_req_ibss)); + memset(bss.bssid, 0xff, ETH_ALEN); + memcpy(bss.essid, priv->essid, IW_ESSID_MAX_SIZE); + bss.essid_size = priv->essid_size; + bss.bss_type = ADHOC_MODE; + bss.channel = priv->channel; + + ret = at76_set_card_command(priv->udev, CMD_START_IBSS, &bss, + sizeof(struct at76_req_ibss)); + if (ret < 0) { + printk(KERN_ERR "%s: start_ibss failed: %d\n", + priv->netdev->name, ret); + return ret; + } + + ret = at76_wait_completion(priv, CMD_START_IBSS); + if (ret != CMD_STATUS_COMPLETE) { + printk(KERN_ERR "%s: start_ibss failed to complete, %d\n", + priv->netdev->name, ret); + return ret; + } + + ret = at76_get_current_bssid(priv); + if (ret < 0) + return ret; + + ret = at76_get_current_channel(priv); + if (ret < 0) + return ret; + + /* not sure what this is good for ??? */ + priv->mib_buf.type = MIB_MAC_MGMT; + priv->mib_buf.size = 1; + priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change); + priv->mib_buf.data.byte = 0; + + ret = at76_set_mib(priv, &priv->mib_buf); + if (ret < 0) { + printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n", + priv->netdev->name, ret); + return ret; + } + + netif_carrier_on(priv->netdev); + netif_start_queue(priv->netdev); + return 0; +} + +/* Request card to join BSS in managed or ad-hoc mode */ +static int at76_join_bss(struct at76_priv *priv, struct bss_info *ptr) +{ + struct at76_req_join join; + + BUG_ON(!ptr); + + memset(&join, 0, sizeof(struct at76_req_join)); + memcpy(join.bssid, ptr->bssid, ETH_ALEN); + memcpy(join.essid, ptr->ssid, ptr->ssid_len); + join.essid_size = ptr->ssid_len; + join.bss_type = (priv->iw_mode == IW_MODE_ADHOC ? 1 : 2); + join.channel = ptr->channel; + join.timeout = cpu_to_le16(2000); + + at76_dbg(DBG_PROGRESS, + "%s join addr %s ssid %s type %d ch %d timeout %d", + priv->netdev->n |