From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 07:43:50 +0000 Subject: [PATCH] rtl88x2CE_WiFi_linux driver --- kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_iw.c | 379 +++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 261 insertions(+), 118 deletions(-) diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_iw.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_iw.c index e99eb33..78fd08e 100644 --- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_iw.c +++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_iw.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0 */ /* * Linux Wireless Extensions support * - * Copyright (C) 1999-2019, Broadcom Corporation - * + * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation + * + * Copyright (C) 1999-2017, Broadcom Corporation + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -17,7 +18,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -25,7 +26,7 @@ * * <<Broadcom-WL-IPTag/Open:>> * - * $Id: wl_iw.c 709309 2019-01-17 09:04:00Z $ + * $Id: wl_iw.c 693575 2017-04-04 06:45:00Z $ */ #if defined(USE_IW) @@ -37,15 +38,14 @@ #include <bcmutils.h> #include <bcmendian.h> -#include <proto/ethernet.h> - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include <linux/sched/signal.h> -#endif +#include <ethernet.h> #include <linux/if_arp.h> -#include <linux/uaccess.h> - +#include <asm/uaccess.h> +#include <linux/signal.h> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) +#include <linux/sched/signal.h> +#endif // endif #include <wlioctl.h> #include <wlioctl_utils.h> @@ -54,35 +54,60 @@ #include <wl_dbg.h> #include <wl_iw.h> +#ifdef BCMWAPI_WPI +/* these items should evetually go into wireless.h of the linux system headfile dir */ +#ifndef IW_ENCODE_ALG_SM4 +#define IW_ENCODE_ALG_SM4 0x20 +#endif // endif + +#ifndef IW_AUTH_WAPI_ENABLED +#define IW_AUTH_WAPI_ENABLED 0x20 +#endif // endif + +#ifndef IW_AUTH_WAPI_VERSION_1 +#define IW_AUTH_WAPI_VERSION_1 0x00000008 +#endif // endif + +#ifndef IW_AUTH_CIPHER_SMS4 +#define IW_AUTH_CIPHER_SMS4 0x00000020 +#endif // endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK +#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 +#endif // endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT +#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 +#endif // endif +#endif /* BCMWAPI_WPI */ /* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */ #ifndef IW_AUTH_KEY_MGMT_FT_802_1X #define IW_AUTH_KEY_MGMT_FT_802_1X 0x04 -#endif +#endif // endif #ifndef IW_AUTH_KEY_MGMT_FT_PSK #define IW_AUTH_KEY_MGMT_FT_PSK 0x08 -#endif +#endif // endif #ifndef IW_ENC_CAPA_FW_ROAM_ENABLE #define IW_ENC_CAPA_FW_ROAM_ENABLE 0x00000020 -#endif - +#endif // endif /* FC9: wireless.h 2.6.25-14.fc9.i686 is missing these, even though WIRELESS_EXT is set to latest * version 22. */ #ifndef IW_ENCODE_ALG_PMK #define IW_ENCODE_ALG_PMK 4 -#endif +#endif // endif #ifndef IW_ENC_CAPA_4WAY_HANDSHAKE #define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 -#endif +#endif // endif /* End FC9. */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) #include <linux/rtnetlink.h> -#endif +#endif // endif #if defined(SOFTAP) struct net_device *ap_net_dev = NULL; tsk_ctl_t ap_eth_ctl; /* apsta AP netdev waiter thread */ @@ -93,7 +118,7 @@ uint wl_msg_level = WL_ERROR_VAL; -#define MAX_WLIW_IOCTL_LEN 1024 +#define MAX_WLIW_IOCTL_LEN WLC_IOCTL_MEDLEN /* IOCTL swapping mode for Big Endian host with Little Endian dongle. Default to off */ #define htod32(i) (i) @@ -110,7 +135,6 @@ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) #endif /* WIRELESS_EXT < 19 */ - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) #define DAEMONIZE(a) do { \ @@ -143,7 +167,7 @@ typedef struct iscan_info { struct net_device *dev; - struct timer_list timer; + timer_list_compat_t timer; uint32 timer_ms; uint32 timer_on; int iscan_state; @@ -153,11 +177,10 @@ /* Thread to work on iscan */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) struct task_struct *kthread; -#endif +#endif // endif long sysioc_pid; struct semaphore sysioc_sem; struct completion sysioc_exited; - char ioctlbuf[WLC_IOCTL_SMLEN]; } iscan_info_t; @@ -176,7 +199,7 @@ #define WL_DEV_LINK(dev) (priv_link_t*)(dev->priv) #else #define WL_DEV_LINK(dev) (priv_link_t*)netdev_priv(dev) -#endif +#endif // endif /* dev to wl_iw_t */ #define IW_DEV_IF(dev) ((wl_iw_t*)(WL_DEV_LINK(dev))->wliw) @@ -217,7 +240,9 @@ { struct ifreq ifr; wl_ioctl_t ioc; +#if defined(KERNEL_DS) && defined(USER_DS) mm_segment_t fs; +#endif /* KERNEL_DS && USER_DS */ int ret; memset(&ioc, 0, sizeof(ioc)); @@ -229,14 +254,20 @@ ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; ifr.ifr_data = (caddr_t) &ioc; +#if defined(KERNEL_DS) && defined(USER_DS) fs = get_fs(); - set_fs(KERNEL_DS); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 0, 21) + set_fs(get_ds()); +#endif // endif +#endif /* KERNEL_DS && USER_DS */ #if defined(WL_USE_NETDEV_OPS) ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); #else ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); -#endif +#endif // endif +#if defined(KERNEL_DS) && defined(USER_DS) set_fs(fs); +#endif /* KERNEL_DS && USER_DS */ return ret; } @@ -576,9 +607,10 @@ while (fwrq->e++ < 6) fwrq->m /= 10; } - /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */ - if (fwrq->m > 4000 && fwrq->m < 5000) - sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */ + /* handle 4.9GHz frequencies as Japan 4 GHz based channelization */ + if (fwrq->m > 4000 && fwrq->m < 5000) { + sf = WF_CHAN_FACTOR_4_G; /* start factor for 4 GHz */ + } chan = wf_mhz2channel(fwrq->m, sf); } @@ -683,17 +715,10 @@ static int channels[MAXCHANNEL+1]; wl_uint32_list_t *list = (wl_uint32_list_t *) channels; wl_rateset_t rateset; - int error, i, k; + int error, i; uint sf, ch; int phytype; - int bw_cap = 0, sgi_tx = 0, nmode = 0; - channel_info_t ci; - uint8 nrate_list2copy = 0; - uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130}, - {14, 29, 43, 58, 87, 116, 130, 144}, - {27, 54, 81, 108, 162, 216, 243, 270}, - {30, 60, 90, 120, 180, 240, 270, 300}}; int fbt_cap = 0; WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); @@ -750,41 +775,8 @@ range->num_bitrates = rateset.count; for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */ - if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode))) - return error; if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)))) return error; - if (nmode == 1 && (((phytype == WLC_PHY_TYPE_LCN) || - (phytype == WLC_PHY_TYPE_LCN40)))) { - if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap))) - return error; - if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx))) - return error; - if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)))) - return error; - ci.hw_channel = dtoh32(ci.hw_channel); - - if (bw_cap == 0 || - (bw_cap == 2 && ci.hw_channel <= 14)) { - if (sgi_tx == 0) - nrate_list2copy = 0; - else - nrate_list2copy = 1; - } - if (bw_cap == 1 || - (bw_cap == 2 && ci.hw_channel >= 36)) { - if (sgi_tx == 0) - nrate_list2copy = 2; - else - nrate_list2copy = 3; - } - range->num_bitrates += 8; - ASSERT(range->num_bitrates < IW_MAX_BITRATES); - for (k = 0; i < range->num_bitrates; k++, i++) { - /* convert to bps */ - range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000; - } - } /* Set an indication of the max TCP throughput * in bit/s that we can expect using this interface. @@ -812,7 +804,7 @@ range->encoding_size[2] = TKIP_KEY_SIZE; #else range->encoding_size[2] = 0; -#endif +#endif // endif range->encoding_size[3] = AES_KEY_SIZE; /* Do not support power micro-management */ @@ -878,7 +870,7 @@ #if WIRELESS_EXT >= 22 && defined(IW_SCAN_CAPA_ESSID) /* FC7 wireless.h defines EXT 22 but doesn't define scan_capa bits */ range->scan_capa = IW_SCAN_CAPA_ESSID; -#endif +#endif // endif #endif /* WIRELESS_EXT > 17 */ return 0; @@ -1091,7 +1083,8 @@ ASSERT(list->version == WL_BSS_INFO_VERSION); for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; + bi = (bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : + (wl_bss_info_t*)list->bss_info); ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + buflen)); @@ -1222,7 +1215,7 @@ ssid.SSID_len = htod32(ssid.SSID_len); } } -#endif +#endif // endif /* Ignore error (most likely scan in progress) */ (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid)); @@ -1263,16 +1256,18 @@ ssid.SSID_len = htod32(ssid.SSID_len); } } -#endif +#endif // endif iscan->list_cur = iscan->list_hdr; iscan->iscan_state = ISCAN_STATE_SCANING; - wl_iw_set_event_mask(dev); wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); - +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +#else + iscan->timer.timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +#endif // endif add_timer(&iscan->timer); iscan->timer_on = 1; @@ -1325,6 +1320,42 @@ } #endif /* WIRELESS_EXT > 17 */ +#ifdef BCMWAPI_WPI +static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, + size_t len, int uppercase) +{ + size_t i; + char *pos = buf, *end = buf + buf_size; + int ret; + if (buf_size == 0) + return 0; + for (i = 0; i < len; i++) { + ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", + data[i]); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return pos - buf; + } + pos += ret; + } + end[-1] = '\0'; + return pos - buf; +} + +/** + * wpa_snprintf_hex - Print data as a hex string into a buffer + * @buf: Memory area to use as the output buffer + * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) + * @data: Data to be printed + * @len: Length of data in bytes + * Returns: Number of bytes written + */ +static int +wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) +{ + return _wpa_snprintf_hex(buf, buf_size, data, len, 0); +} +#endif /* BCMWAPI_WPI */ static int wl_iw_handle_scanresults_ies(char **event_p, char *end, @@ -1333,13 +1364,17 @@ #if WIRELESS_EXT > 17 struct iw_event iwe; char *event; +#ifdef BCMWAPI_WPI + char *buf; + int custom_event_len; +#endif // endif event = *event_p; if (bi->ie_length) { /* look for wpa/rsn ies in the ie list... */ bcm_tlv_t *ie; uint8 *ptr = ((uint8 *)bi) + bi->ie_offset; - int ptr_len = bi->ie_length; + uint ptr_len = bi->ie_length; /* OSEN IE */ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_VS_ID)) && @@ -1387,6 +1422,38 @@ } } +#ifdef BCMWAPI_WPI + ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); + ptr_len = bi->ie_length; + + while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) { + WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__)); +#ifdef WAPI_IE_USE_GENIE + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie->len + 2; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +#else /* using CUSTOM event */ + iwe.cmd = IWEVCUSTOM; + custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2); + iwe.u.data.length = custom_event_len; + + buf = kmalloc(custom_event_len+1, GFP_KERNEL); + if (buf == NULL) + { + WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len)); + break; + } + + memcpy(buf, "wapi_ie=", 8); + wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1); + wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1); + wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len); + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf); + kfree(buf); +#endif /* WAPI_IE_USE_GENIE */ + break; + } +#endif /* BCMWAPI_WPI */ *event_p = event; } @@ -1438,7 +1505,8 @@ ASSERT(list->version == WL_BSS_INFO_VERSION); for (i = 0; i < list->count && i < IW_MAX_AP; i++) { - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; + bi = (bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : + (wl_bss_info_t *)list->bss_info); ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + buflen)); @@ -1480,7 +1548,6 @@ iwe.u.qual.noise = 0x100 + bi->phy_noise; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); - /* WPA, WPA2, WPS, WAPI IEs */ wl_iw_handle_scanresults_ies(&event, end, info, bi); /* Encryption */ @@ -1604,7 +1671,6 @@ iwe.u.qual.noise = 0x100 + bi->phy_noise; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); - /* WPA, WPA2, WPS, WAPI IEs */ wl_iw_handle_scanresults_ies(&event, end, info, bi); /* Encryption */ @@ -1644,7 +1710,6 @@ #endif /* WIRELESS_EXT > 13 */ - static int wl_iw_set_essid( struct net_device *dev, @@ -1665,7 +1730,7 @@ ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length); #else ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1); -#endif +#endif // endif memcpy(ssid.SSID, extra, ssid.SSID_len); ssid.SSID_len = htod32(ssid.SSID_len); @@ -1705,8 +1770,16 @@ ssid.SSID_len = dtoh32(ssid.SSID_len); + /* Max SSID length check */ + if (ssid.SSID_len > IW_ESSID_MAX_SIZE) { + ssid.SSID_len = IW_ESSID_MAX_SIZE; + } + /* Get the current SSID */ memcpy(extra, ssid.SSID, ssid.SSID_len); + + /* NULL terminating as length of extra buffer is IW_ESSID_MAX_SIZE ie 32 */ + extra[IW_ESSID_MAX_SIZE] = '\0'; dwrq->length = ssid.SSID_len; @@ -1974,7 +2047,6 @@ if (vwrq->value > 0xffff) txpwrmw = 0xffff; else txpwrmw = (uint16)vwrq->value; - error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw))); return error; } @@ -2161,7 +2233,7 @@ case TKIP_KEY_SIZE: key.algo = CRYPTO_ALGO_TKIP; break; -#endif +#endif // endif case AES_KEY_SIZE: key.algo = CRYPTO_ALGO_AES_CCM; break; @@ -2299,6 +2371,21 @@ char *extra ) { +#if defined(BCMWAPI_WPI) + uchar buf[WLC_IOCTL_SMLEN] = {0}; + uchar *p = buf; + int wapi_ie_size; + + WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name)); + + if (extra[0] == DOT11_MNG_WAPI_ID) + { + wapi_ie_size = iwp->length; + memcpy(p, extra, iwp->length); + dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size); + } + else +#endif // endif dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); return 0; @@ -2441,6 +2528,14 @@ case IW_ENCODE_ALG_CCMP: key.algo = CRYPTO_ALGO_AES_CCM; break; +#ifdef BCMWAPI_WPI + case IW_ENCODE_ALG_SM4: + key.algo = CRYPTO_ALGO_SMS4; + if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + key.flags &= ~WL_PRIMARY_KEY; + } + break; +#endif // endif default: break; } @@ -2454,7 +2549,6 @@ } return 0; } - #if WIRELESS_EXT > 17 struct { @@ -2590,6 +2684,10 @@ val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; else if (paramval & IW_AUTH_WPA_VERSION_WPA2) val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; +#ifdef BCMWAPI_WPI + else if (paramval & IW_AUTH_WAPI_VERSION_1) + val = WAPI_AUTH_UNSPECIFIED; +#endif // endif WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) return error; @@ -2617,6 +2715,11 @@ val |= TKIP_ENABLED; if (cipher_combined & IW_AUTH_CIPHER_CCMP) val |= AES_ENABLED; +#ifdef BCMWAPI_WPI + val &= ~SMS4_ENABLED; + if (cipher_combined & IW_AUTH_CIPHER_SMS4) + val |= SMS4_ENABLED; +#endif // endif if (iw->privacy_invoked && !val) { WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming " @@ -2673,6 +2776,10 @@ if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) val |= WPA2_AUTH_FT; } +#ifdef BCMWAPI_WPI + if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT)) + val = WAPI_AUTH_UNSPECIFIED; +#endif // endif WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) return error; @@ -2752,9 +2859,31 @@ break; } - #endif /* WIRELESS_EXT > 17 */ +#ifdef BCMWAPI_WPI + + case IW_AUTH_WAPI_ENABLED: + if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) + return error; + if (paramval) { + val |= SMS4_ENABLED; + if ((error = dev_wlc_intvar_set(dev, "wsec", val))) { + WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n", + __FUNCTION__, val, error)); + return error; + } + if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WAPI_AUTH_UNSPECIFIED))) { + WL_ERROR(("%s: setting wpa_auth(%d) returned %d\n", + __FUNCTION__, WAPI_AUTH_UNSPECIFIED, + error)); + return error; + } + } + + break; + +#endif /* BCMWAPI_WPI */ default: break; @@ -2888,7 +3017,7 @@ (iw_handler) wl_iw_mlme, /* SIOCSIWMLME */ #else (iw_handler) NULL, /* -- hole -- */ -#endif +#endif // endif (iw_handler) wl_iw_iscan_get_aplist, /* SIOCGIWAPLIST */ #if WIRELESS_EXT > 13 (iw_handler) wl_iw_iscan_set_scan, /* SIOCSIWSCAN */ @@ -3022,7 +3151,7 @@ #if WIRELESS_EXT > 17 case SIOCSIWENCODEEXT: case SIOCGIWENCODEEXT: -#endif +#endif // endif max_tokens = IW_ENCODING_TOKEN_MAX; break; @@ -3037,10 +3166,13 @@ #if WIRELESS_EXT > 13 case SIOCGIWSCAN: - if (g_iscan) + if (g_iscan) { max_tokens = wrq->u.data.length; + } else - max_tokens = IW_SCAN_MAX_DATA; + { + max_tokens = IW_SCAN_MAX_DATA; + } break; #endif /* WIRELESS_EXT > 13 */ @@ -3317,7 +3449,7 @@ case WLC_E_SCAN_COMPLETE: #if WIRELESS_EXT > 14 cmd = SIOCGIWSCAN; -#endif +#endif // endif WL_TRACE(("event WLC_E_SCAN_COMPLETE\n")); if ((g_iscan) && (g_iscan->sysioc_pid >= 0) && (g_iscan->iscan_state != ISCAN_STATE_IDLE)) @@ -3351,14 +3483,15 @@ #endif /* WIRELESS_EXT > 13 */ } -static int wl_iw_get_wireless_stats_cbfn(void *ctx, uint8 *data, uint16 type, uint16 len) +static int wl_iw_get_wireless_stats_cbfn(void *ctx, const uint8 *data, + uint16 type, uint16 len) { struct iw_statistics *wstats = ctx; int res = BCME_OK; switch (type) { case WL_CNT_XTLV_WLC: { - wl_cnt_wlc_t *cnt = (wl_cnt_wlc_t *)data; + const wl_cnt_wlc_t *cnt = (const wl_cnt_wlc_t *)data; if (len > sizeof(wl_cnt_wlc_t)) { printf("counter structure length invalid! %d > %d\n", len, (int)sizeof(wl_cnt_wlc_t)); @@ -3391,7 +3524,7 @@ * wl_cnt_v_le10_mcst_t, wl_cnt_lt40mcst_v1_t, and wl_cnt_ge40mcst_v1_t. * So we can just cast to wl_cnt_v_le10_mcst_t here. */ - wl_cnt_v_le10_mcst_t *cnt = (wl_cnt_v_le10_mcst_t *)data; + const wl_cnt_v_le10_mcst_t *cnt = (const wl_cnt_v_le10_mcst_t *)data; if (len != WL_CNT_MCST_STRUCT_SZ) { printf("counter structure length mismatch! %d != %d\n", len, WL_CNT_MCST_STRUCT_SZ); @@ -3459,24 +3592,16 @@ #endif /* WIRELESS_EXT > 18 */ #if WIRELESS_EXT > 11 - WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", WL_CNTBUF_MAX_SIZE)); + WL_TRACE(("wl_iw_get_wireless_stats counters\n *****")); - if (WL_CNTBUF_MAX_SIZE > MAX_WLIW_IOCTL_LEN) - { - WL_ERROR(("wl_iw_get_wireless_stats buffer too short %d < %d\n", - WL_CNTBUF_MAX_SIZE, MAX_WLIW_IOCTL_LEN)); - res = BCME_BUFTOOSHORT; - goto done; - } - - cntbuf = kmalloc(WL_CNTBUF_MAX_SIZE, GFP_KERNEL); + cntbuf = kmalloc(MAX_WLIW_IOCTL_LEN, GFP_KERNEL); if (!cntbuf) { res = BCME_NOMEM; goto done; } - memset(cntbuf, 0, WL_CNTBUF_MAX_SIZE); - res = dev_wlc_bufvar_get(dev, "counters", cntbuf, WL_CNTBUF_MAX_SIZE); + memset(cntbuf, 0, MAX_WLIW_IOCTL_LEN); + res = dev_wlc_bufvar_get(dev, "counters", cntbuf, MAX_WLIW_IOCTL_LEN); if (res) { WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res)); @@ -3487,6 +3612,7 @@ cntinfo->version = dtoh16(cntinfo->version); cntinfo->datalen = dtoh16(cntinfo->datalen); ver = cntinfo->version; + CHK_CNTBUF_DATALEN(cntbuf, MAX_WLIW_IOCTL_LEN); if (ver > WL_CNT_T_VERSION) { WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n", WL_CNT_T_VERSION, ver)); @@ -3505,7 +3631,7 @@ corerev = dtoh32(revinfo.corerev); } - res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, WL_CNTBUF_MAX_SIZE, corerev); + res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, MAX_WLIW_IOCTL_LEN, corerev); if (res) { WL_ERROR(("%s: wl_cntbuf_to_xtlv_format failed %d\n", __FUNCTION__, res)); goto done; @@ -3691,25 +3817,30 @@ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_lock(); -#endif +#endif // endif status = wl_iw_iscan_get(iscan); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_unlock(); -#endif +#endif // endif switch (status) { case WL_SCAN_RESULTS_PARTIAL: WL_TRACE(("iscanresults incomplete\n")); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_lock(); -#endif +#endif // endif /* make sure our buffer size is enough before going next round */ wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_unlock(); -#endif +#endif // endif /* Reschedule the timer */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +#else + iscan->timer.timer.expires = jiffies + + msecs_to_jiffies(iscan->timer_ms); +#endif // endif add_timer(&iscan->timer); iscan->timer_on = 1; break; @@ -3721,7 +3852,12 @@ case WL_SCAN_RESULTS_PENDING: WL_TRACE(("iscanresults pending\n")); /* Reschedule the timer */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) iscan->timer.expires = jiffies + msecs_to_jiffies(iscan->timer_ms); +#else + iscan->timer.timer.expires = jiffies + + msecs_to_jiffies(iscan->timer_ms); +#endif // endif add_timer(&iscan->timer); iscan->timer_on = 1; break; @@ -3752,20 +3888,22 @@ memset(iscan, 0, sizeof(iscan_info_t)); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) iscan->kthread = NULL; -#endif +#endif // endif iscan->sysioc_pid = -1; /* we only care about main interface so save a global here */ g_iscan = iscan; iscan->dev = dev; iscan->iscan_state = ISCAN_STATE_IDLE; - /* Set up the timer */ iscan->timer_ms = 2000; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)) init_timer(&iscan->timer); iscan->timer.data = (ulong)iscan; iscan->timer.function = wl_iw_timerfunc; - +#else + init_timer_compat(&iscan->timer, wl_iw_timerfunc, iscan); +#endif // endif sema_init(&iscan->sysioc_sem, 0); init_completion(&iscan->sysioc_exited); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) @@ -3773,7 +3911,7 @@ iscan->sysioc_pid = iscan->kthread->pid; #else iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); -#endif +#endif // endif if (iscan->sysioc_pid < 0) return -ENOMEM; return 0; @@ -3785,6 +3923,11 @@ iscan_info_t *iscan = g_iscan; if (!iscan) return; + /* Delete iscan timer */ + if (iscan->timer_on) { + del_timer_sync(&iscan->timer); + iscan->timer_on = 0; + } if (iscan->sysioc_pid >= 0) { KILL_PROC(iscan->sysioc_pid, SIGTERM); wait_for_completion(&iscan->sysioc_exited); -- Gitblit v1.6.2