1*4882a593Smuzhiyun /** @file moal_wext.c
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * @brief This file contains wireless extension standard ioctl functions
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2008-2021 NXP
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This software file (the File) is distributed by NXP
9*4882a593Smuzhiyun * under the terms of the GNU General Public License Version 2, June 1991
10*4882a593Smuzhiyun * (the License). You may use, redistribute and/or modify the File in
11*4882a593Smuzhiyun * accordance with the terms and conditions of the License, a copy of which
12*4882a593Smuzhiyun * is available by writing to the Free Software Foundation, Inc.,
13*4882a593Smuzhiyun * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14*4882a593Smuzhiyun * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17*4882a593Smuzhiyun * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18*4882a593Smuzhiyun * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19*4882a593Smuzhiyun * this warranty disclaimer.
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /************************************************************************
24*4882a593Smuzhiyun Change log:
25*4882a593Smuzhiyun 10/21/2008: initial version
26*4882a593Smuzhiyun ************************************************************************/
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include "moal_main.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #ifdef STA_SUPPORT
31*4882a593Smuzhiyun /** Approximate amount of data needed to pass a scan result back to iwlist */
32*4882a593Smuzhiyun #define MAX_SCAN_CELL_SIZE \
33*4882a593Smuzhiyun (IW_EV_ADDR_LEN + MLAN_MAX_SSID_LENGTH + IW_EV_UINT_LEN + \
34*4882a593Smuzhiyun IW_EV_FREQ_LEN + IW_EV_QUAL_LEN + MLAN_MAX_SSID_LENGTH + \
35*4882a593Smuzhiyun IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /********************************************************
38*4882a593Smuzhiyun Local Variables
39*4882a593Smuzhiyun ********************************************************/
40*4882a593Smuzhiyun /**
41*4882a593Smuzhiyun * iwpriv ioctl handlers
42*4882a593Smuzhiyun */
43*4882a593Smuzhiyun static const struct iw_priv_args woal_private_args[] = {
44*4882a593Smuzhiyun {WOAL_SETONEINT_GETWORDCHAR, IW_PRIV_TYPE_INT | 1,
45*4882a593Smuzhiyun IW_PRIV_TYPE_CHAR | 128, ""},
46*4882a593Smuzhiyun {WOAL_VERSION, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128,
47*4882a593Smuzhiyun "version"},
48*4882a593Smuzhiyun {WOAL_VEREXT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128, "verext"},
49*4882a593Smuzhiyun {WOAL_SETNONE_GETNONE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, ""},
50*4882a593Smuzhiyun {WOAL_WARMRESET, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "warmreset"},
51*4882a593Smuzhiyun #ifdef CONFIG_USB_SUSPEND
52*4882a593Smuzhiyun {WOAL_USB_SUSPEND, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "usbsuspend"},
53*4882a593Smuzhiyun {WOAL_USB_RESUME, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "usbresume"},
54*4882a593Smuzhiyun #endif /* CONFIG_USB_SUSPEND */
55*4882a593Smuzhiyun {WOAL_SETONEINT_GETONEINT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
56*4882a593Smuzhiyun ""},
57*4882a593Smuzhiyun {WOAL_SET_GET_TXRATE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
58*4882a593Smuzhiyun "txratecfg"},
59*4882a593Smuzhiyun {WOAL_SET_GET_REGIONCODE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
60*4882a593Smuzhiyun "regioncode"},
61*4882a593Smuzhiyun {WOAL_SET_RADIO, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
62*4882a593Smuzhiyun "radioctrl"},
63*4882a593Smuzhiyun {WOAL_WMM_ENABLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "wmmcfg"},
64*4882a593Smuzhiyun {WOAL_11D_ENABLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "11dcfg"},
65*4882a593Smuzhiyun {WOAL_11D_CLR_CHAN_TABLE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE,
66*4882a593Smuzhiyun "11dclrtbl"},
67*4882a593Smuzhiyun {WOAL_SET_GET_QOS_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
68*4882a593Smuzhiyun "qoscfg"},
69*4882a593Smuzhiyun #ifndef OPCHAN
70*4882a593Smuzhiyun {WOAL_SET_GET_WWS_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
71*4882a593Smuzhiyun "wwscfg"},
72*4882a593Smuzhiyun #endif
73*4882a593Smuzhiyun #if defined(REASSOCIATION)
74*4882a593Smuzhiyun {WOAL_SET_GET_REASSOC, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
75*4882a593Smuzhiyun "reassoctrl"},
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun {WOAL_TXBUF_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
78*4882a593Smuzhiyun "txbufcfg"},
79*4882a593Smuzhiyun {WOAL_SLEEP_PD, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "sleeppd"},
80*4882a593Smuzhiyun {WOAL_AUTH_TYPE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
81*4882a593Smuzhiyun "authtype"},
82*4882a593Smuzhiyun {WOAL_PORT_CTRL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
83*4882a593Smuzhiyun "port_ctrl"},
84*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
85*4882a593Smuzhiyun #if defined(STA_SUPPORT) && defined(UAP_SUPPORT)
86*4882a593Smuzhiyun {WOAL_SET_GET_BSS_ROLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
87*4882a593Smuzhiyun "bssrole"},
88*4882a593Smuzhiyun #endif
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun {WOAL_SET_GET_11H_LOCAL_PWR_CONSTRAINT, IW_PRIV_TYPE_INT | 1,
91*4882a593Smuzhiyun IW_PRIV_TYPE_INT | 1, "powercons"},
92*4882a593Smuzhiyun {WOAL_HT_STREAM_CFG, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
93*4882a593Smuzhiyun "htstreamcfg"},
94*4882a593Smuzhiyun {WOAL_MAC_CONTROL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
95*4882a593Smuzhiyun "macctrl"},
96*4882a593Smuzhiyun {WOAL_THERMAL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "thermal"},
97*4882a593Smuzhiyun {WOAL_CFG_HOTSPOT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1,
98*4882a593Smuzhiyun "hotspotcfg"},
99*4882a593Smuzhiyun {WOAL_SET_GET_SIXTEEN_INT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
100*4882a593Smuzhiyun ""},
101*4882a593Smuzhiyun {WOAL_TX_POWERCFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
102*4882a593Smuzhiyun "txpowercfg"},
103*4882a593Smuzhiyun #ifdef DEBUG_LEVEL1
104*4882a593Smuzhiyun {WOAL_DRV_DBG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "drvdbg"},
105*4882a593Smuzhiyun #endif
106*4882a593Smuzhiyun {WOAL_BEACON_INTERVAL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
107*4882a593Smuzhiyun "bcninterval"},
108*4882a593Smuzhiyun {WOAL_SIGNAL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
109*4882a593Smuzhiyun "getsignal"},
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun WOAL_DEEP_SLEEP,
112*4882a593Smuzhiyun IW_PRIV_TYPE_INT | 16,
113*4882a593Smuzhiyun IW_PRIV_TYPE_INT | 16,
114*4882a593Smuzhiyun "deepsleep",
115*4882a593Smuzhiyun },
116*4882a593Smuzhiyun {WOAL_11N_TX_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
117*4882a593Smuzhiyun "httxcfg"},
118*4882a593Smuzhiyun {WOAL_11N_HTCAP_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
119*4882a593Smuzhiyun "htcapinfo"},
120*4882a593Smuzhiyun {WOAL_PRIO_TBL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
121*4882a593Smuzhiyun "aggrpriotbl"},
122*4882a593Smuzhiyun {WOAL_11N_AMSDU_AGGR_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
123*4882a593Smuzhiyun "amsduaggrctrl"},
124*4882a593Smuzhiyun {WOAL_ADDBA_UPDT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
125*4882a593Smuzhiyun "addbapara"},
126*4882a593Smuzhiyun {WOAL_ADDBA_REJECT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
127*4882a593Smuzhiyun "addbareject"},
128*4882a593Smuzhiyun {WOAL_TX_BF_CAP, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
129*4882a593Smuzhiyun "httxbfcap"},
130*4882a593Smuzhiyun {WOAL_HS_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "hscfg"},
131*4882a593Smuzhiyun {WOAL_HS_SETPARA, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
132*4882a593Smuzhiyun "hssetpara"},
133*4882a593Smuzhiyun {WOAL_REG_READ_WRITE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
134*4882a593Smuzhiyun "regrdwr"},
135*4882a593Smuzhiyun {WOAL_BAND_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
136*4882a593Smuzhiyun "bandcfg"},
137*4882a593Smuzhiyun {WOAL_INACTIVITY_TIMEOUT_EXT, IW_PRIV_TYPE_INT | 16,
138*4882a593Smuzhiyun IW_PRIV_TYPE_INT | 16, "inactivityto"},
139*4882a593Smuzhiyun #ifdef SDIO
140*4882a593Smuzhiyun {WOAL_SDIO_CLOCK, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
141*4882a593Smuzhiyun "sdioclock"},
142*4882a593Smuzhiyun {WOAL_CMD_52RDWR, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
143*4882a593Smuzhiyun "sdcmd52rw"},
144*4882a593Smuzhiyun #endif
145*4882a593Smuzhiyun {WOAL_SCAN_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
146*4882a593Smuzhiyun "scancfg"},
147*4882a593Smuzhiyun {WOAL_PS_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "pscfg"},
148*4882a593Smuzhiyun {WOAL_MEM_READ_WRITE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
149*4882a593Smuzhiyun "memrdwr"},
150*4882a593Smuzhiyun #ifdef SDIO
151*4882a593Smuzhiyun {WOAL_SDIO_MPA_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
152*4882a593Smuzhiyun "mpactrl"},
153*4882a593Smuzhiyun #endif
154*4882a593Smuzhiyun {WOAL_SLEEP_PARAMS, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
155*4882a593Smuzhiyun "sleepparams"},
156*4882a593Smuzhiyun {WOAL_NET_MONITOR, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
157*4882a593Smuzhiyun "netmon"},
158*4882a593Smuzhiyun {WOAL_DFS_TESTING, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
159*4882a593Smuzhiyun "dfstesting"},
160*4882a593Smuzhiyun {WOAL_MGMT_FRAME_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
161*4882a593Smuzhiyun "mgmtframectrl"},
162*4882a593Smuzhiyun {WOAL_CFP_CODE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
163*4882a593Smuzhiyun "cfpcode"},
164*4882a593Smuzhiyun {WOAL_SET_GET_TX_RX_ANT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
165*4882a593Smuzhiyun "antcfg"},
166*4882a593Smuzhiyun {WOAL_IND_RST_CFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16,
167*4882a593Smuzhiyun "indrstcfg"},
168*4882a593Smuzhiyun {WOALGETLOG, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | GETLOG_BUFSIZE,
169*4882a593Smuzhiyun "getlog"},
170*4882a593Smuzhiyun {WOAL_SETADDR_GETNONE, IW_PRIV_TYPE_ADDR | 1, IW_PRIV_TYPE_NONE, ""},
171*4882a593Smuzhiyun {WOAL_DEAUTH, IW_PRIV_TYPE_ADDR | 1, IW_PRIV_TYPE_NONE, "deauth"},
172*4882a593Smuzhiyun {WOAL_SET_GET_256_CHAR, IW_PRIV_TYPE_CHAR | 256,
173*4882a593Smuzhiyun IW_PRIV_TYPE_CHAR | 256, ""},
174*4882a593Smuzhiyun {WOAL_PASSPHRASE, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
175*4882a593Smuzhiyun "passphrase"},
176*4882a593Smuzhiyun {WOAL_GET_KEY, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
177*4882a593Smuzhiyun "getkey"},
178*4882a593Smuzhiyun {WOAL_ASSOCIATE, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
179*4882a593Smuzhiyun "associate"},
180*4882a593Smuzhiyun {WOAL_WMM_QUEUE_STATUS, IW_PRIV_TYPE_CHAR | 256,
181*4882a593Smuzhiyun IW_PRIV_TYPE_CHAR | 256, "qstatus"},
182*4882a593Smuzhiyun {WOAL_WMM_TS_STATUS, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
183*4882a593Smuzhiyun "ts_status"},
184*4882a593Smuzhiyun {WOAL_IP_ADDRESS, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
185*4882a593Smuzhiyun "ipaddr"},
186*4882a593Smuzhiyun {WOAL_TX_BF_CFG, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256,
187*4882a593Smuzhiyun "httxbfcfg"},
188*4882a593Smuzhiyun {WOAL_SETNONE_GETTWELVE_CHAR, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12,
189*4882a593Smuzhiyun ""},
190*4882a593Smuzhiyun {WOAL_WPS_SESSION, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12,
191*4882a593Smuzhiyun "wpssession"},
192*4882a593Smuzhiyun {WOAL_SETNONE_GET_FOUR_INT, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | 4,
193*4882a593Smuzhiyun ""},
194*4882a593Smuzhiyun {WOAL_DATA_RATE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | 4,
195*4882a593Smuzhiyun "getdatarate"},
196*4882a593Smuzhiyun {WOAL_ESUPP_MODE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | 4, "esuppmode"},
197*4882a593Smuzhiyun {WOAL_SET_GET_64_INT, IW_PRIV_TYPE_INT | 64, IW_PRIV_TYPE_INT | 64, ""},
198*4882a593Smuzhiyun {WOAL_ECL_SYS_CLOCK, IW_PRIV_TYPE_INT | 64, IW_PRIV_TYPE_INT | 64,
199*4882a593Smuzhiyun "sysclock"},
200*4882a593Smuzhiyun {WOAL_HOST_CMD, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047,
201*4882a593Smuzhiyun "hostcmd"},
202*4882a593Smuzhiyun {WOAL_ARP_FILTER, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047,
203*4882a593Smuzhiyun "arpfilter"},
204*4882a593Smuzhiyun {WOAL_SET_INTS_GET_CHARS, IW_PRIV_TYPE_INT | 16,
205*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | 256, ""},
206*4882a593Smuzhiyun {WOAL_READ_EEPROM, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_BYTE | 256,
207*4882a593Smuzhiyun "rdeeprom"},
208*4882a593Smuzhiyun {WOAL_SET_GET_2K_BYTES, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
209*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, ""},
210*4882a593Smuzhiyun #if defined(SDIO)
211*4882a593Smuzhiyun {WOAL_CMD_53RDWR, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
212*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "sdcmd53rw"},
213*4882a593Smuzhiyun #endif
214*4882a593Smuzhiyun {WOAL_SET_USER_SCAN, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
215*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "setuserscan"},
216*4882a593Smuzhiyun {WOAL_GET_SCAN_TABLE, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
217*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "getscantable"},
218*4882a593Smuzhiyun {WOAL_SET_USER_SCAN_EXT, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
219*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "setuserscanext"},
220*4882a593Smuzhiyun {WOAL_WMM_ADDTS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
221*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "addts"},
222*4882a593Smuzhiyun {WOAL_WMM_DELTS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
223*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "delts"},
224*4882a593Smuzhiyun {WOAL_WMM_QUEUE_CONFIG, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
225*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "qconfig"},
226*4882a593Smuzhiyun {WOAL_WMM_QUEUE_STATS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
227*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "qstats"},
228*4882a593Smuzhiyun {WOAL_BYPASSED_PACKET, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES,
229*4882a593Smuzhiyun IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "pb_bypass"},
230*4882a593Smuzhiyun #ifdef UAP_WEXT
231*4882a593Smuzhiyun {WOAL_FROYO_START, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "START"},
232*4882a593Smuzhiyun {WOAL_FROYO_STOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, "STOP"},
233*4882a593Smuzhiyun {WOAL_FROYO_WL_FW_RELOAD, IW_PRIV_TYPE_CHAR | 256,
234*4882a593Smuzhiyun IW_PRIV_TYPE_CHAR | 256, "WL_FW_RELOAD"},
235*4882a593Smuzhiyun #endif
236*4882a593Smuzhiyun };
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /********************************************************
239*4882a593Smuzhiyun Local Functions
240*4882a593Smuzhiyun ********************************************************/
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /**
243*4882a593Smuzhiyun * @brief Compare two SSIDs
244*4882a593Smuzhiyun *
245*4882a593Smuzhiyun * @param ssid1 A pointer to ssid to compare
246*4882a593Smuzhiyun * @param ssid2 A pointer to ssid to compare
247*4882a593Smuzhiyun *
248*4882a593Smuzhiyun * @return 0--ssid is same, otherwise is different
249*4882a593Smuzhiyun */
woal_ssid_cmp(mlan_802_11_ssid * ssid1,mlan_802_11_ssid * ssid2)250*4882a593Smuzhiyun static t_s32 woal_ssid_cmp(mlan_802_11_ssid *ssid1, mlan_802_11_ssid *ssid2)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun ENTER();
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun if (!ssid1 || !ssid2) {
255*4882a593Smuzhiyun LEAVE();
256*4882a593Smuzhiyun return -1;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun if (ssid1->ssid_len != ssid2->ssid_len) {
259*4882a593Smuzhiyun LEAVE();
260*4882a593Smuzhiyun return -1;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun LEAVE();
264*4882a593Smuzhiyun return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun * @brief Sort Channels
269*4882a593Smuzhiyun *
270*4882a593Smuzhiyun * @param freq A pointer to iw_freq structure
271*4882a593Smuzhiyun * @param num Number of Channels
272*4882a593Smuzhiyun *
273*4882a593Smuzhiyun * @return N/A
274*4882a593Smuzhiyun */
woal_sort_channels(struct iw_freq * freq,int num)275*4882a593Smuzhiyun static inline void woal_sort_channels(struct iw_freq *freq, int num)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun int i, j;
278*4882a593Smuzhiyun struct iw_freq temp;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun for (i = 0; i < num; i++)
281*4882a593Smuzhiyun for (j = i + 1; j < num; j++)
282*4882a593Smuzhiyun if (freq[i].i > freq[j].i) {
283*4882a593Smuzhiyun temp.i = freq[i].i;
284*4882a593Smuzhiyun temp.m = freq[i].m;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun freq[i].i = freq[j].i;
287*4882a593Smuzhiyun freq[i].m = freq[j].m;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun freq[j].i = temp.i;
290*4882a593Smuzhiyun freq[j].m = temp.m;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /**
295*4882a593Smuzhiyun * @brief Convert RSSI to quality
296*4882a593Smuzhiyun *
297*4882a593Smuzhiyun * @param rssi RSSI in dBm
298*4882a593Smuzhiyun *
299*4882a593Smuzhiyun * @return Quality of the link (0-5)
300*4882a593Smuzhiyun */
woal_rssi_to_quality(t_s16 rssi)301*4882a593Smuzhiyun static t_u8 woal_rssi_to_quality(t_s16 rssi)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun /** Macro for RSSI range */
304*4882a593Smuzhiyun #define MOAL_RSSI_NO_SIGNAL -90
305*4882a593Smuzhiyun #define MOAL_RSSI_VERY_LOW -80
306*4882a593Smuzhiyun #define MOAL_RSSI_LOW -70
307*4882a593Smuzhiyun #define MOAL_RSSI_GOOD -60
308*4882a593Smuzhiyun #define MOAL_RSSI_VERY_GOOD -50
309*4882a593Smuzhiyun #define MOAL_RSSI_INVALID 0
310*4882a593Smuzhiyun if (rssi <= MOAL_RSSI_NO_SIGNAL || rssi == MOAL_RSSI_INVALID)
311*4882a593Smuzhiyun return 0;
312*4882a593Smuzhiyun else if (rssi <= MOAL_RSSI_VERY_LOW)
313*4882a593Smuzhiyun return 1;
314*4882a593Smuzhiyun else if (rssi <= MOAL_RSSI_LOW)
315*4882a593Smuzhiyun return 2;
316*4882a593Smuzhiyun else if (rssi <= MOAL_RSSI_GOOD)
317*4882a593Smuzhiyun return 3;
318*4882a593Smuzhiyun else if (rssi <= MOAL_RSSI_VERY_GOOD)
319*4882a593Smuzhiyun return 4;
320*4882a593Smuzhiyun else
321*4882a593Smuzhiyun return 5;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /**
325*4882a593Smuzhiyun * @brief Set Adapter Node Name
326*4882a593Smuzhiyun *
327*4882a593Smuzhiyun * @param dev A pointer to net_device structure
328*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
329*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
330*4882a593Smuzhiyun * @param extra A pointer to extra data buf
331*4882a593Smuzhiyun *
332*4882a593Smuzhiyun * @return 0 --success, otherwise fail
333*4882a593Smuzhiyun */
woal_set_nick(struct net_device * dev,struct iw_request_info * info,struct iw_point * dwrq,char * extra)334*4882a593Smuzhiyun static int woal_set_nick(struct net_device *dev, struct iw_request_info *info,
335*4882a593Smuzhiyun struct iw_point *dwrq, char *extra)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
338*4882a593Smuzhiyun ENTER();
339*4882a593Smuzhiyun /*
340*4882a593Smuzhiyun * Check the size of the string
341*4882a593Smuzhiyun */
342*4882a593Smuzhiyun if (dwrq->length > 16) {
343*4882a593Smuzhiyun LEAVE();
344*4882a593Smuzhiyun return -E2BIG;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun memset(priv->nick_name, 0, sizeof(priv->nick_name));
347*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, priv->nick_name, extra, dwrq->length,
348*4882a593Smuzhiyun sizeof(priv->nick_name));
349*4882a593Smuzhiyun LEAVE();
350*4882a593Smuzhiyun return 0;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /**
354*4882a593Smuzhiyun * @brief Get Adapter Node Name
355*4882a593Smuzhiyun *
356*4882a593Smuzhiyun * @param dev A pointer to net_device structure
357*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
358*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
359*4882a593Smuzhiyun * @param extra A pointer to extra data buf
360*4882a593Smuzhiyun *
361*4882a593Smuzhiyun * @return 0 --success
362*4882a593Smuzhiyun */
woal_get_nick(struct net_device * dev,struct iw_request_info * info,struct iw_point * dwrq,char * extra)363*4882a593Smuzhiyun static int woal_get_nick(struct net_device *dev, struct iw_request_info *info,
364*4882a593Smuzhiyun struct iw_point *dwrq, char *extra)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
367*4882a593Smuzhiyun ENTER();
368*4882a593Smuzhiyun /*
369*4882a593Smuzhiyun * Get the Nick Name saved
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun strncpy(extra, (char *)priv->nick_name, 16);
372*4882a593Smuzhiyun extra[16] = '\0';
373*4882a593Smuzhiyun /*
374*4882a593Smuzhiyun * If none, we may want to get the one that was set
375*4882a593Smuzhiyun */
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun * Push it out !
379*4882a593Smuzhiyun */
380*4882a593Smuzhiyun dwrq->length = strlen(extra) + 1;
381*4882a593Smuzhiyun LEAVE();
382*4882a593Smuzhiyun return 0;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun /**
386*4882a593Smuzhiyun * @brief Commit handler: called after a bunch of SET operations
387*4882a593Smuzhiyun *
388*4882a593Smuzhiyun * @param dev A pointer to net_device structure
389*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
390*4882a593Smuzhiyun * @param cwrq A pointer to char buffer
391*4882a593Smuzhiyun * @param extra A pointer to extra data buf
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun * @return 0 --success
394*4882a593Smuzhiyun */
woal_config_commit(struct net_device * dev,struct iw_request_info * info,union iwreq_data * cwrq,char * extra)395*4882a593Smuzhiyun static int woal_config_commit(struct net_device *dev,
396*4882a593Smuzhiyun struct iw_request_info *info,
397*4882a593Smuzhiyun union iwreq_data *cwrq, char *extra)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun ENTER();
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun LEAVE();
402*4882a593Smuzhiyun return 0;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /**
406*4882a593Smuzhiyun * @brief Get name
407*4882a593Smuzhiyun *
408*4882a593Smuzhiyun * @param dev A pointer to net_device structure
409*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
410*4882a593Smuzhiyun * @param cwrq A pointer to char buffer
411*4882a593Smuzhiyun * @param extra A pointer to extra data buf
412*4882a593Smuzhiyun *
413*4882a593Smuzhiyun * @return 0 --success
414*4882a593Smuzhiyun */
woal_get_name(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)415*4882a593Smuzhiyun static int woal_get_name(struct net_device *dev, struct iw_request_info *info,
416*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun char *cwrq = wrqu->name;
419*4882a593Smuzhiyun ENTER();
420*4882a593Smuzhiyun strcpy(cwrq, "IEEE 802.11-DS");
421*4882a593Smuzhiyun LEAVE();
422*4882a593Smuzhiyun return 0;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun /**
426*4882a593Smuzhiyun * @brief Set frequency
427*4882a593Smuzhiyun *
428*4882a593Smuzhiyun * @param dev A pointer to net_device structure
429*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
430*4882a593Smuzhiyun * @param fwrq A pointer to iw_freq structure
431*4882a593Smuzhiyun * @param extra A pointer to extra data buf
432*4882a593Smuzhiyun *
433*4882a593Smuzhiyun * @return 0 --success, otherwise fail
434*4882a593Smuzhiyun */
woal_set_freq(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)435*4882a593Smuzhiyun static int woal_set_freq(struct net_device *dev, struct iw_request_info *info,
436*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun int ret = 0;
439*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
440*4882a593Smuzhiyun struct iw_freq *fwrq = &wrqu->freq;
441*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
442*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
443*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun ENTER();
446*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
447*4882a593Smuzhiyun if (req == NULL) {
448*4882a593Smuzhiyun ret = -ENOMEM;
449*4882a593Smuzhiyun goto done;
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
452*4882a593Smuzhiyun /*
453*4882a593Smuzhiyun * If setting by frequency, convert to a channel
454*4882a593Smuzhiyun */
455*4882a593Smuzhiyun if (fwrq->e == 1) {
456*4882a593Smuzhiyun long f = fwrq->m / 100000;
457*4882a593Smuzhiyun bss->param.bss_chan.freq = f;
458*4882a593Smuzhiyun } else
459*4882a593Smuzhiyun bss->param.bss_chan.channel = fwrq->m;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun bss->sub_command = MLAN_OID_BSS_CHANNEL;
462*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
463*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
464*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
465*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
466*4882a593Smuzhiyun ret = -EFAULT;
467*4882a593Smuzhiyun goto done;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
470*4882a593Smuzhiyun woal_change_adhoc_chan(priv, bss->param.bss_chan.channel,
471*4882a593Smuzhiyun MOAL_IOCTL_WAIT))
472*4882a593Smuzhiyun ret = -EFAULT;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun done:
475*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
476*4882a593Smuzhiyun kfree(req);
477*4882a593Smuzhiyun LEAVE();
478*4882a593Smuzhiyun return ret;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /**
482*4882a593Smuzhiyun * @brief Get frequency
483*4882a593Smuzhiyun *
484*4882a593Smuzhiyun * @param dev A pointer to net_device structure
485*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
486*4882a593Smuzhiyun * @param fwrq A pointer to iw_freq structure
487*4882a593Smuzhiyun * @param extra A pointer to extra data buf
488*4882a593Smuzhiyun *
489*4882a593Smuzhiyun * @return 0 --success, otherwise fail
490*4882a593Smuzhiyun */
woal_get_freq(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)491*4882a593Smuzhiyun static int woal_get_freq(struct net_device *dev, struct iw_request_info *info,
492*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun int ret = 0;
495*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
496*4882a593Smuzhiyun struct iw_freq *fwrq = &wrqu->freq;
497*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
498*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
499*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun ENTER();
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
504*4882a593Smuzhiyun if (req == NULL) {
505*4882a593Smuzhiyun ret = -ENOMEM;
506*4882a593Smuzhiyun goto done;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
509*4882a593Smuzhiyun bss->sub_command = MLAN_OID_BSS_CHANNEL;
510*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
511*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
512*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
513*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
514*4882a593Smuzhiyun ret = -EFAULT;
515*4882a593Smuzhiyun goto done;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun fwrq->m = (long)bss->param.bss_chan.freq;
518*4882a593Smuzhiyun fwrq->i = (long)bss->param.bss_chan.channel;
519*4882a593Smuzhiyun fwrq->e = 6;
520*4882a593Smuzhiyun fwrq->flags = IW_FREQ_FIXED;
521*4882a593Smuzhiyun done:
522*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
523*4882a593Smuzhiyun kfree(req);
524*4882a593Smuzhiyun LEAVE();
525*4882a593Smuzhiyun return ret;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun /**
529*4882a593Smuzhiyun * @brief Set wlan mode
530*4882a593Smuzhiyun *
531*4882a593Smuzhiyun * @param dev A pointer to net_device structure
532*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
533*4882a593Smuzhiyun * @param uwrq Wireless mode to set
534*4882a593Smuzhiyun * @param extra A pointer to extra data buf
535*4882a593Smuzhiyun *
536*4882a593Smuzhiyun * @return 0 --success, otherwise fail
537*4882a593Smuzhiyun */
woal_set_bss_mode(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)538*4882a593Smuzhiyun static int woal_set_bss_mode(struct net_device *dev,
539*4882a593Smuzhiyun struct iw_request_info *info,
540*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun int ret = 0;
543*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
544*4882a593Smuzhiyun t_u32 *uwrq = &wrqu->mode;
545*4882a593Smuzhiyun mlan_ds_bss *bss = NULL;
546*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
547*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun ENTER();
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
552*4882a593Smuzhiyun if (req == NULL) {
553*4882a593Smuzhiyun ret = -ENOMEM;
554*4882a593Smuzhiyun goto done;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun bss = (mlan_ds_bss *)req->pbuf;
557*4882a593Smuzhiyun bss->sub_command = MLAN_OID_BSS_MODE;
558*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_BSS;
559*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun switch (*uwrq) {
562*4882a593Smuzhiyun case IW_MODE_INFRA:
563*4882a593Smuzhiyun bss->param.bss_mode = MLAN_BSS_MODE_INFRA;
564*4882a593Smuzhiyun break;
565*4882a593Smuzhiyun case IW_MODE_ADHOC:
566*4882a593Smuzhiyun bss->param.bss_mode = MLAN_BSS_MODE_IBSS;
567*4882a593Smuzhiyun break;
568*4882a593Smuzhiyun case IW_MODE_AUTO:
569*4882a593Smuzhiyun bss->param.bss_mode = MLAN_BSS_MODE_AUTO;
570*4882a593Smuzhiyun break;
571*4882a593Smuzhiyun default:
572*4882a593Smuzhiyun ret = -EINVAL;
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun if (ret)
576*4882a593Smuzhiyun goto done;
577*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
578*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
579*4882a593Smuzhiyun ret = -EFAULT;
580*4882a593Smuzhiyun goto done;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun done:
583*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
584*4882a593Smuzhiyun kfree(req);
585*4882a593Smuzhiyun LEAVE();
586*4882a593Smuzhiyun return ret;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun /**
590*4882a593Smuzhiyun * @brief Get current BSSID
591*4882a593Smuzhiyun *
592*4882a593Smuzhiyun * @param dev A pointer to net_device structure
593*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
594*4882a593Smuzhiyun * @param awrq A pointer to sockaddr structure
595*4882a593Smuzhiyun * @param extra A pointer to extra data buf
596*4882a593Smuzhiyun *
597*4882a593Smuzhiyun * @return 0 --success
598*4882a593Smuzhiyun */
woal_get_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)599*4882a593Smuzhiyun static int woal_get_wap(struct net_device *dev, struct iw_request_info *info,
600*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun int ret = 0;
603*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
604*4882a593Smuzhiyun struct sockaddr *awrq = &wrqu->addr;
605*4882a593Smuzhiyun mlan_bss_info bss_info;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun ENTER();
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun if (bss_info.media_connected == MTRUE)
614*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, awrq->sa_data, &bss_info.bssid,
615*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH, sizeof(awrq->sa_data));
616*4882a593Smuzhiyun else
617*4882a593Smuzhiyun memset(awrq->sa_data, 0, MLAN_MAC_ADDR_LENGTH);
618*4882a593Smuzhiyun awrq->sa_family = ARPHRD_ETHER;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun LEAVE();
621*4882a593Smuzhiyun return ret;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun /**
625*4882a593Smuzhiyun * @brief Connect to the AP or Ad-hoc Network with specific bssid
626*4882a593Smuzhiyun *
627*4882a593Smuzhiyun * NOTE: Scan should be issued by application before this function is called
628*4882a593Smuzhiyun *
629*4882a593Smuzhiyun * @param dev A pointer to net_device structure
630*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
631*4882a593Smuzhiyun * @param awrq A pointer to iw_param structure
632*4882a593Smuzhiyun * @param extra A pointer to extra data buf
633*4882a593Smuzhiyun *
634*4882a593Smuzhiyun * @return 0 --success, otherwise fail
635*4882a593Smuzhiyun */
woal_set_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)636*4882a593Smuzhiyun static int woal_set_wap(struct net_device *dev, struct iw_request_info *info,
637*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun int ret = 0;
640*4882a593Smuzhiyun const t_u8 bcast[MLAN_MAC_ADDR_LENGTH] = {255, 255, 255, 255, 255, 255};
641*4882a593Smuzhiyun const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0, 0, 0, 0, 0, 0};
642*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
643*4882a593Smuzhiyun struct sockaddr *awrq = &wrqu->addr;
644*4882a593Smuzhiyun mlan_ssid_bssid ssid_bssid;
645*4882a593Smuzhiyun mlan_bss_info bss_info;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun ENTER();
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun if (awrq->sa_family != ARPHRD_ETHER) {
650*4882a593Smuzhiyun ret = -EINVAL;
651*4882a593Smuzhiyun goto done;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun PRINTM(MINFO, "ASSOC: WAP: sa_data: " MACSTR "\n",
655*4882a593Smuzhiyun MAC2STR((t_u8 *)awrq->sa_data));
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
658*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
659*4882a593Smuzhiyun ret = -EFAULT;
660*4882a593Smuzhiyun goto done;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun #ifdef REASSOCIATION
664*4882a593Smuzhiyun /* Cancel re-association */
665*4882a593Smuzhiyun priv->reassoc_required = MFALSE;
666*4882a593Smuzhiyun #endif
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* zero_mac means disconnect */
669*4882a593Smuzhiyun if (!memcmp(zero_mac, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
670*4882a593Smuzhiyun woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
671*4882a593Smuzhiyun DEF_DEAUTH_REASON_CODE);
672*4882a593Smuzhiyun goto done;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun /* Broadcast MAC means search for best network */
676*4882a593Smuzhiyun memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun if (memcmp(bcast, awrq->sa_data, MLAN_MAC_ADDR_LENGTH)) {
679*4882a593Smuzhiyun /* Check if we are already assoicated to the AP */
680*4882a593Smuzhiyun if (bss_info.media_connected == MTRUE) {
681*4882a593Smuzhiyun if (!memcmp(awrq->sa_data, &bss_info.bssid, ETH_ALEN))
682*4882a593Smuzhiyun goto done;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &ssid_bssid.bssid, awrq->sa_data,
685*4882a593Smuzhiyun ETH_ALEN, sizeof(ssid_bssid.bssid));
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
689*4882a593Smuzhiyun woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
690*4882a593Smuzhiyun PRINTM(MERROR,
691*4882a593Smuzhiyun "ASSOC: WAP: MAC address not found in BSSID List\n");
692*4882a593Smuzhiyun ret = -ENETUNREACH;
693*4882a593Smuzhiyun goto done;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun /* Zero SSID implies use BSSID to connect */
696*4882a593Smuzhiyun memset(&ssid_bssid.ssid, 0, sizeof(mlan_802_11_ssid));
697*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
698*4882a593Smuzhiyun woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
699*4882a593Smuzhiyun ret = -EFAULT;
700*4882a593Smuzhiyun goto done;
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun #ifdef REASSOCIATION
704*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
705*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
706*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
707*4882a593Smuzhiyun ret = -EFAULT;
708*4882a593Smuzhiyun goto done;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
711*4882a593Smuzhiyun &bss_info.ssid, sizeof(mlan_802_11_ssid),
712*4882a593Smuzhiyun sizeof(priv->prev_ssid_bssid.ssid));
713*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
714*4882a593Smuzhiyun &bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
715*4882a593Smuzhiyun sizeof(priv->prev_ssid_bssid.bssid));
716*4882a593Smuzhiyun #endif /* REASSOCIATION */
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun done:
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun LEAVE();
721*4882a593Smuzhiyun return ret;
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun /**
725*4882a593Smuzhiyun * @brief Get wlan mode
726*4882a593Smuzhiyun *
727*4882a593Smuzhiyun * @param dev A pointer to net_device structure
728*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
729*4882a593Smuzhiyun * @param uwrq A pointer to t_u32 string
730*4882a593Smuzhiyun * @param extra A pointer to extra data buf
731*4882a593Smuzhiyun *
732*4882a593Smuzhiyun * @return 0 --success
733*4882a593Smuzhiyun */
woal_get_bss_mode(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)734*4882a593Smuzhiyun static int woal_get_bss_mode(struct net_device *dev,
735*4882a593Smuzhiyun struct iw_request_info *info,
736*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
739*4882a593Smuzhiyun t_u32 *uwrq = &wrqu->mode;
740*4882a593Smuzhiyun ENTER();
741*4882a593Smuzhiyun *uwrq = woal_get_mode(priv, MOAL_IOCTL_WAIT);
742*4882a593Smuzhiyun LEAVE();
743*4882a593Smuzhiyun return 0;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun /**
747*4882a593Smuzhiyun * @brief Set sensitivity
748*4882a593Smuzhiyun *
749*4882a593Smuzhiyun * @param dev A pointer to net_device structure
750*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
751*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
752*4882a593Smuzhiyun * @param extra A pointer to extra data buf
753*4882a593Smuzhiyun *
754*4882a593Smuzhiyun * @return 0 --success
755*4882a593Smuzhiyun */
woal_set_sens(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)756*4882a593Smuzhiyun static int woal_set_sens(struct net_device *dev, struct iw_request_info *info,
757*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun int ret = 0;
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun ENTER();
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun LEAVE();
764*4882a593Smuzhiyun return ret;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun /**
768*4882a593Smuzhiyun * @brief Get sensitivity
769*4882a593Smuzhiyun *
770*4882a593Smuzhiyun * @param dev A pointer to net_device structure
771*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
772*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
773*4882a593Smuzhiyun * @param extra A pointer to extra data buf
774*4882a593Smuzhiyun *
775*4882a593Smuzhiyun * @return -1
776*4882a593Smuzhiyun */
woal_get_sens(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)777*4882a593Smuzhiyun static int woal_get_sens(struct net_device *dev, struct iw_request_info *info,
778*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun int ret = -1;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun ENTER();
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun LEAVE();
785*4882a593Smuzhiyun return ret;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun /**
789*4882a593Smuzhiyun * @brief Set Tx power
790*4882a593Smuzhiyun *
791*4882a593Smuzhiyun * @param dev A pointer to net_device structure
792*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
793*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
794*4882a593Smuzhiyun * @param extra A pointer to extra data buf
795*4882a593Smuzhiyun *
796*4882a593Smuzhiyun * @return 0 --success, otherwise fail
797*4882a593Smuzhiyun */
woal_set_txpow(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)798*4882a593Smuzhiyun static int woal_set_txpow(struct net_device *dev, struct iw_request_info *info,
799*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun int ret = 0;
802*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
803*4882a593Smuzhiyun mlan_power_cfg_t power_cfg;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun ENTER();
806*4882a593Smuzhiyun if (vwrq->disabled) {
807*4882a593Smuzhiyun woal_set_radio(priv, 0);
808*4882a593Smuzhiyun goto done;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun woal_set_radio(priv, 1);
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (!vwrq->fixed)
813*4882a593Smuzhiyun power_cfg.is_power_auto = 1;
814*4882a593Smuzhiyun else {
815*4882a593Smuzhiyun power_cfg.is_power_auto = 0;
816*4882a593Smuzhiyun power_cfg.power_level = vwrq->value;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
820*4882a593Smuzhiyun woal_set_get_tx_power(priv, MLAN_ACT_SET, &power_cfg)) {
821*4882a593Smuzhiyun ret = -EFAULT;
822*4882a593Smuzhiyun goto done;
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun done:
826*4882a593Smuzhiyun LEAVE();
827*4882a593Smuzhiyun return ret;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun /**
831*4882a593Smuzhiyun * @brief Get Tx power
832*4882a593Smuzhiyun *
833*4882a593Smuzhiyun * @param dev A pointer to net_device structure
834*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
835*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
836*4882a593Smuzhiyun * @param extra A pointer to extra data buf
837*4882a593Smuzhiyun *
838*4882a593Smuzhiyun * @return 0 --success, otherwise fail
839*4882a593Smuzhiyun */
woal_get_txpow(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)840*4882a593Smuzhiyun static int woal_get_txpow(struct net_device *dev, struct iw_request_info *info,
841*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun int ret = 0;
844*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
845*4882a593Smuzhiyun mlan_power_cfg_t power_cfg;
846*4882a593Smuzhiyun mlan_bss_info bss_info;
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun ENTER();
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun memset(&power_cfg, 0, sizeof(mlan_power_cfg_t));
851*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
852*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
855*4882a593Smuzhiyun woal_set_get_tx_power(priv, MLAN_ACT_GET, &power_cfg)) {
856*4882a593Smuzhiyun ret = -EFAULT;
857*4882a593Smuzhiyun goto done;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun vwrq->value = power_cfg.power_level;
861*4882a593Smuzhiyun if (power_cfg.is_power_auto)
862*4882a593Smuzhiyun vwrq->fixed = 0;
863*4882a593Smuzhiyun else
864*4882a593Smuzhiyun vwrq->fixed = 1;
865*4882a593Smuzhiyun if (bss_info.radio_on) {
866*4882a593Smuzhiyun vwrq->disabled = 0;
867*4882a593Smuzhiyun vwrq->flags = IW_TXPOW_DBM;
868*4882a593Smuzhiyun } else {
869*4882a593Smuzhiyun vwrq->disabled = 1;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun done:
873*4882a593Smuzhiyun LEAVE();
874*4882a593Smuzhiyun return ret;
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun /**
878*4882a593Smuzhiyun * @brief Set power management
879*4882a593Smuzhiyun *
880*4882a593Smuzhiyun * @param dev A pointer to net_device structure
881*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
882*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
883*4882a593Smuzhiyun * @param extra A pointer to extra data buf
884*4882a593Smuzhiyun *
885*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS --success, otherwise fail
886*4882a593Smuzhiyun */
woal_set_power(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)887*4882a593Smuzhiyun static int woal_set_power(struct net_device *dev, struct iw_request_info *info,
888*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun int ret = 0, disabled;
891*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun ENTER();
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun if (moal_extflg_isset(priv->phandle, EXT_HW_TEST)) {
896*4882a593Smuzhiyun PRINTM(MIOCTL, "block set power in hw_test mode\n");
897*4882a593Smuzhiyun LEAVE();
898*4882a593Smuzhiyun return ret;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun disabled = vwrq->disabled;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
903*4882a593Smuzhiyun woal_set_get_power_mgmt(priv, MLAN_ACT_SET, &disabled, vwrq->flags,
904*4882a593Smuzhiyun MOAL_IOCTL_WAIT)) {
905*4882a593Smuzhiyun ret = -EFAULT;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun LEAVE();
909*4882a593Smuzhiyun return ret;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun /**
913*4882a593Smuzhiyun * @brief Get power management
914*4882a593Smuzhiyun *
915*4882a593Smuzhiyun * @param dev A pointer to net_device structure
916*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
917*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
918*4882a593Smuzhiyun * @param extra A pointer to extra data buf
919*4882a593Smuzhiyun *
920*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS --success, otherwise fail
921*4882a593Smuzhiyun */
woal_get_power(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)922*4882a593Smuzhiyun static int woal_get_power(struct net_device *dev, struct iw_request_info *info,
923*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun int ret = 0, ps_mode = 0;
926*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun ENTER();
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, MLAN_ACT_GET,
931*4882a593Smuzhiyun &ps_mode, 0,
932*4882a593Smuzhiyun MOAL_IOCTL_WAIT)) {
933*4882a593Smuzhiyun ret = -EFAULT;
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun if (ps_mode)
937*4882a593Smuzhiyun vwrq->disabled = 0;
938*4882a593Smuzhiyun else
939*4882a593Smuzhiyun vwrq->disabled = 1;
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun vwrq->value = 0;
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun LEAVE();
944*4882a593Smuzhiyun return ret;
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun /**
948*4882a593Smuzhiyun * @brief Set Tx retry count
949*4882a593Smuzhiyun *
950*4882a593Smuzhiyun * @param dev A pointer to net_device structure
951*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
952*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
953*4882a593Smuzhiyun * @param extra A pointer to extra data buf
954*4882a593Smuzhiyun *
955*4882a593Smuzhiyun * @return 0 --success, otherwise fail
956*4882a593Smuzhiyun */
woal_set_retry(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)957*4882a593Smuzhiyun static int woal_set_retry(struct net_device *dev, struct iw_request_info *info,
958*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun int ret = 0, retry_val = vwrq->value;
961*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun ENTER();
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun if (vwrq->flags == IW_RETRY_LIMIT) {
966*4882a593Smuzhiyun /*
967*4882a593Smuzhiyun * The MAC has a 4-bit Total_Tx_Count register
968*4882a593Smuzhiyun * Total_Tx_Count = 1 + Tx_Retry_Count
969*4882a593Smuzhiyun */
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
972*4882a593Smuzhiyun woal_set_get_retry(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
973*4882a593Smuzhiyun &retry_val)) {
974*4882a593Smuzhiyun ret = -EFAULT;
975*4882a593Smuzhiyun goto done;
976*4882a593Smuzhiyun }
977*4882a593Smuzhiyun } else {
978*4882a593Smuzhiyun ret = -EOPNOTSUPP;
979*4882a593Smuzhiyun goto done;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun done:
983*4882a593Smuzhiyun LEAVE();
984*4882a593Smuzhiyun return ret;
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun /**
988*4882a593Smuzhiyun * @brief Get Tx retry count
989*4882a593Smuzhiyun *
990*4882a593Smuzhiyun * @param dev A pointer to net_device structure
991*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
992*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
993*4882a593Smuzhiyun * @param extra A pointer to extra data buf
994*4882a593Smuzhiyun *
995*4882a593Smuzhiyun * @return 0 --success, otherwise fail
996*4882a593Smuzhiyun */
woal_get_retry(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)997*4882a593Smuzhiyun static int woal_get_retry(struct net_device *dev, struct iw_request_info *info,
998*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
999*4882a593Smuzhiyun {
1000*4882a593Smuzhiyun int retry_val, ret = 0;
1001*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun ENTER();
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_retry(priv, MLAN_ACT_GET,
1006*4882a593Smuzhiyun MOAL_IOCTL_WAIT,
1007*4882a593Smuzhiyun &retry_val)) {
1008*4882a593Smuzhiyun ret = -EFAULT;
1009*4882a593Smuzhiyun goto done;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun vwrq->disabled = 0;
1013*4882a593Smuzhiyun if (!vwrq->flags) {
1014*4882a593Smuzhiyun vwrq->flags = IW_RETRY_LIMIT;
1015*4882a593Smuzhiyun /* Get Tx retry count */
1016*4882a593Smuzhiyun vwrq->value = retry_val;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun done:
1020*4882a593Smuzhiyun LEAVE();
1021*4882a593Smuzhiyun return ret;
1022*4882a593Smuzhiyun }
1023*4882a593Smuzhiyun
1024*4882a593Smuzhiyun /**
1025*4882a593Smuzhiyun * @brief Set encryption key
1026*4882a593Smuzhiyun *
1027*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1028*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1029*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1030*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1031*4882a593Smuzhiyun *
1032*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1033*4882a593Smuzhiyun */
woal_set_encode(struct net_device * dev,struct iw_request_info * info,struct iw_point * dwrq,char * extra)1034*4882a593Smuzhiyun static int woal_set_encode(struct net_device *dev, struct iw_request_info *info,
1035*4882a593Smuzhiyun struct iw_point *dwrq, char *extra)
1036*4882a593Smuzhiyun {
1037*4882a593Smuzhiyun int ret = 0;
1038*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1039*4882a593Smuzhiyun mlan_ds_sec_cfg *sec = NULL;
1040*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
1041*4882a593Smuzhiyun int index = 0;
1042*4882a593Smuzhiyun t_u32 auth_mode = 0;
1043*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun ENTER();
1046*4882a593Smuzhiyun
1047*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
1048*4882a593Smuzhiyun if (req == NULL) {
1049*4882a593Smuzhiyun ret = -ENOMEM;
1050*4882a593Smuzhiyun goto done;
1051*4882a593Smuzhiyun }
1052*4882a593Smuzhiyun sec = (mlan_ds_sec_cfg *)req->pbuf;
1053*4882a593Smuzhiyun sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
1054*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_SEC_CFG;
1055*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun /* Check index */
1058*4882a593Smuzhiyun index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1059*4882a593Smuzhiyun if (index > 3) {
1060*4882a593Smuzhiyun PRINTM(MERROR, "Key index #%d out of range\n", index);
1061*4882a593Smuzhiyun ret = -EINVAL;
1062*4882a593Smuzhiyun goto done;
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun sec->param.encrypt_key.key_len = 0;
1066*4882a593Smuzhiyun if (!(dwrq->flags & IW_ENCODE_NOKEY) && dwrq->length) {
1067*4882a593Smuzhiyun if (dwrq->length > MAX_WEP_KEY_SIZE) {
1068*4882a593Smuzhiyun PRINTM(MERROR, "Key length (%d) out of range\n",
1069*4882a593Smuzhiyun dwrq->length);
1070*4882a593Smuzhiyun ret = -EINVAL;
1071*4882a593Smuzhiyun goto done;
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun if (index < 0)
1074*4882a593Smuzhiyun sec->param.encrypt_key.key_index =
1075*4882a593Smuzhiyun MLAN_KEY_INDEX_DEFAULT;
1076*4882a593Smuzhiyun else
1077*4882a593Smuzhiyun sec->param.encrypt_key.key_index = index;
1078*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
1079*4882a593Smuzhiyun sec->param.encrypt_key.key_material, extra,
1080*4882a593Smuzhiyun dwrq->length,
1081*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.key_material));
1082*4882a593Smuzhiyun /* Set the length */
1083*4882a593Smuzhiyun if (dwrq->length > MIN_WEP_KEY_SIZE)
1084*4882a593Smuzhiyun sec->param.encrypt_key.key_len = MAX_WEP_KEY_SIZE;
1085*4882a593Smuzhiyun else
1086*4882a593Smuzhiyun sec->param.encrypt_key.key_len = MIN_WEP_KEY_SIZE;
1087*4882a593Smuzhiyun } else {
1088*4882a593Smuzhiyun /*
1089*4882a593Smuzhiyun * No key provided so it is either enable key,
1090*4882a593Smuzhiyun * on or off
1091*4882a593Smuzhiyun */
1092*4882a593Smuzhiyun if (dwrq->flags & IW_ENCODE_DISABLED) {
1093*4882a593Smuzhiyun PRINTM(MINFO, "*** iwconfig mlanX key off ***\n");
1094*4882a593Smuzhiyun sec->param.encrypt_key.key_disable = MTRUE;
1095*4882a593Smuzhiyun } else {
1096*4882a593Smuzhiyun /*
1097*4882a593Smuzhiyun * iwconfig mlanX key [n]
1098*4882a593Smuzhiyun * iwconfig mlanX key on
1099*4882a593Smuzhiyun * iwconfig mlanX key open
1100*4882a593Smuzhiyun * iwconfig mlanX key restricted
1101*4882a593Smuzhiyun * Do we want to just set the transmit key index ?
1102*4882a593Smuzhiyun */
1103*4882a593Smuzhiyun if (index < 0) {
1104*4882a593Smuzhiyun PRINTM(MINFO,
1105*4882a593Smuzhiyun "*** iwconfig mlanX key on ***\n");
1106*4882a593Smuzhiyun sec->param.encrypt_key.key_index =
1107*4882a593Smuzhiyun MLAN_KEY_INDEX_DEFAULT;
1108*4882a593Smuzhiyun } else
1109*4882a593Smuzhiyun sec->param.encrypt_key.key_index = index;
1110*4882a593Smuzhiyun sec->param.encrypt_key.is_current_wep_key = MTRUE;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1114*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1115*4882a593Smuzhiyun ret = -EFAULT;
1116*4882a593Smuzhiyun goto done;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun if (dwrq->flags & (IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)) {
1119*4882a593Smuzhiyun switch (dwrq->flags & 0xf000) {
1120*4882a593Smuzhiyun case IW_ENCODE_RESTRICTED:
1121*4882a593Smuzhiyun /* iwconfig mlanX restricted key [1] */
1122*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_SHARED;
1123*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode restricted!\n");
1124*4882a593Smuzhiyun break;
1125*4882a593Smuzhiyun case IW_ENCODE_OPEN:
1126*4882a593Smuzhiyun /* iwconfig mlanX key [2] open */
1127*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_OPEN;
1128*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode open!\n");
1129*4882a593Smuzhiyun break;
1130*4882a593Smuzhiyun case IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN:
1131*4882a593Smuzhiyun default:
1132*4882a593Smuzhiyun /* iwconfig mlanX key [2] open restricted */
1133*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_AUTO;
1134*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode auto!\n");
1135*4882a593Smuzhiyun break;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1138*4882a593Smuzhiyun woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode))
1139*4882a593Smuzhiyun ret = -EFAULT;
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun done:
1142*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1143*4882a593Smuzhiyun kfree(req);
1144*4882a593Smuzhiyun LEAVE();
1145*4882a593Smuzhiyun return ret;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun /**
1149*4882a593Smuzhiyun * @brief Get encryption key
1150*4882a593Smuzhiyun *
1151*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1152*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1153*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1154*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1155*4882a593Smuzhiyun *
1156*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1157*4882a593Smuzhiyun */
woal_get_encode(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1158*4882a593Smuzhiyun static int woal_get_encode(struct net_device *dev, struct iw_request_info *info,
1159*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1160*4882a593Smuzhiyun {
1161*4882a593Smuzhiyun int ret = 0;
1162*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1163*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
1164*4882a593Smuzhiyun mlan_ds_sec_cfg *sec = NULL;
1165*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
1166*4882a593Smuzhiyun t_u32 auth_mode;
1167*4882a593Smuzhiyun int index = (dwrq->flags & IW_ENCODE_INDEX);
1168*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun ENTER();
1171*4882a593Smuzhiyun if (index < 0 || index > 4) {
1172*4882a593Smuzhiyun PRINTM(MERROR, "Key index #%d out of range\n", index);
1173*4882a593Smuzhiyun ret = -EINVAL;
1174*4882a593Smuzhiyun goto done;
1175*4882a593Smuzhiyun }
1176*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1177*4882a593Smuzhiyun woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode)) {
1178*4882a593Smuzhiyun ret = -EFAULT;
1179*4882a593Smuzhiyun goto done;
1180*4882a593Smuzhiyun }
1181*4882a593Smuzhiyun dwrq->flags = 0;
1182*4882a593Smuzhiyun /*
1183*4882a593Smuzhiyun * Check encryption mode
1184*4882a593Smuzhiyun */
1185*4882a593Smuzhiyun switch (auth_mode) {
1186*4882a593Smuzhiyun case MLAN_AUTH_MODE_OPEN:
1187*4882a593Smuzhiyun dwrq->flags = IW_ENCODE_OPEN;
1188*4882a593Smuzhiyun break;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun case MLAN_AUTH_MODE_SHARED:
1191*4882a593Smuzhiyun case MLAN_AUTH_MODE_NETWORKEAP:
1192*4882a593Smuzhiyun dwrq->flags = IW_ENCODE_RESTRICTED;
1193*4882a593Smuzhiyun break;
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun case MLAN_AUTH_MODE_AUTO:
1196*4882a593Smuzhiyun dwrq->flags = IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED;
1197*4882a593Smuzhiyun break;
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun default:
1200*4882a593Smuzhiyun dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
1201*4882a593Smuzhiyun break;
1202*4882a593Smuzhiyun }
1203*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
1204*4882a593Smuzhiyun if (req == NULL) {
1205*4882a593Smuzhiyun ret = -ENOMEM;
1206*4882a593Smuzhiyun goto done;
1207*4882a593Smuzhiyun }
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun sec = (mlan_ds_sec_cfg *)req->pbuf;
1210*4882a593Smuzhiyun sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
1211*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_SEC_CFG;
1212*4882a593Smuzhiyun req->action = MLAN_ACT_GET;
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun if (!index)
1215*4882a593Smuzhiyun sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_DEFAULT;
1216*4882a593Smuzhiyun else
1217*4882a593Smuzhiyun sec->param.encrypt_key.key_index = index - 1;
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1220*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1221*4882a593Smuzhiyun ret = -EFAULT;
1222*4882a593Smuzhiyun goto done;
1223*4882a593Smuzhiyun }
1224*4882a593Smuzhiyun memset(extra, 0, 16);
1225*4882a593Smuzhiyun if (sec->param.encrypt_key.key_len) {
1226*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, extra,
1227*4882a593Smuzhiyun sec->param.encrypt_key.key_material,
1228*4882a593Smuzhiyun sec->param.encrypt_key.key_len,
1229*4882a593Smuzhiyun sec->param.encrypt_key.key_len);
1230*4882a593Smuzhiyun dwrq->length = sec->param.encrypt_key.key_len;
1231*4882a593Smuzhiyun dwrq->flags |= (sec->param.encrypt_key.key_index + 1);
1232*4882a593Smuzhiyun dwrq->flags &= ~IW_ENCODE_DISABLED;
1233*4882a593Smuzhiyun } else if (sec->param.encrypt_key.key_disable)
1234*4882a593Smuzhiyun dwrq->flags |= IW_ENCODE_DISABLED;
1235*4882a593Smuzhiyun else
1236*4882a593Smuzhiyun dwrq->flags &= ~IW_ENCODE_DISABLED;
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun dwrq->flags |= IW_ENCODE_NOKEY;
1239*4882a593Smuzhiyun done:
1240*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1241*4882a593Smuzhiyun kfree(req);
1242*4882a593Smuzhiyun LEAVE();
1243*4882a593Smuzhiyun return ret;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun /**
1247*4882a593Smuzhiyun * @brief Set data rate
1248*4882a593Smuzhiyun *
1249*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1250*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1251*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1252*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1253*4882a593Smuzhiyun *
1254*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1255*4882a593Smuzhiyun */
woal_set_rate(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1256*4882a593Smuzhiyun static int woal_set_rate(struct net_device *dev, struct iw_request_info *info,
1257*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1258*4882a593Smuzhiyun {
1259*4882a593Smuzhiyun int ret = 0;
1260*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1261*4882a593Smuzhiyun mlan_rate_cfg_t rate_cfg;
1262*4882a593Smuzhiyun
1263*4882a593Smuzhiyun ENTER();
1264*4882a593Smuzhiyun
1265*4882a593Smuzhiyun if (vwrq->value == -1) {
1266*4882a593Smuzhiyun rate_cfg.is_rate_auto = 1;
1267*4882a593Smuzhiyun } else {
1268*4882a593Smuzhiyun rate_cfg.is_rate_auto = 0;
1269*4882a593Smuzhiyun rate_cfg.rate_type = MLAN_RATE_VALUE;
1270*4882a593Smuzhiyun rate_cfg.rate = vwrq->value / 500000;
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1273*4882a593Smuzhiyun woal_set_get_data_rate(priv, MLAN_ACT_SET, &rate_cfg)) {
1274*4882a593Smuzhiyun ret = -EFAULT;
1275*4882a593Smuzhiyun }
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun LEAVE();
1278*4882a593Smuzhiyun return ret;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
1281*4882a593Smuzhiyun /**
1282*4882a593Smuzhiyun * @brief Get data rate
1283*4882a593Smuzhiyun *
1284*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1285*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1286*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1287*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1288*4882a593Smuzhiyun *
1289*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1290*4882a593Smuzhiyun */
woal_get_rate(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1291*4882a593Smuzhiyun static int woal_get_rate(struct net_device *dev, struct iw_request_info *info,
1292*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1293*4882a593Smuzhiyun {
1294*4882a593Smuzhiyun int ret = 0;
1295*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1296*4882a593Smuzhiyun mlan_rate_cfg_t rate_cfg;
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun ENTER();
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1301*4882a593Smuzhiyun woal_set_get_data_rate(priv, MLAN_ACT_GET, &rate_cfg)) {
1302*4882a593Smuzhiyun ret = -EFAULT;
1303*4882a593Smuzhiyun goto done;
1304*4882a593Smuzhiyun }
1305*4882a593Smuzhiyun
1306*4882a593Smuzhiyun if (rate_cfg.is_rate_auto)
1307*4882a593Smuzhiyun vwrq->fixed = 0;
1308*4882a593Smuzhiyun else
1309*4882a593Smuzhiyun vwrq->fixed = 1;
1310*4882a593Smuzhiyun vwrq->value = rate_cfg.rate * 500000;
1311*4882a593Smuzhiyun done:
1312*4882a593Smuzhiyun LEAVE();
1313*4882a593Smuzhiyun return ret;
1314*4882a593Smuzhiyun }
1315*4882a593Smuzhiyun
1316*4882a593Smuzhiyun /**
1317*4882a593Smuzhiyun * @brief Set RTS threshold
1318*4882a593Smuzhiyun *
1319*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1320*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1321*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1322*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1323*4882a593Smuzhiyun *
1324*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1325*4882a593Smuzhiyun */
woal_set_rts(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1326*4882a593Smuzhiyun static int woal_set_rts(struct net_device *dev, struct iw_request_info *info,
1327*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1328*4882a593Smuzhiyun {
1329*4882a593Smuzhiyun int ret = 0;
1330*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1331*4882a593Smuzhiyun int rthr = vwrq->value;
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun ENTER();
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun if (vwrq->disabled) {
1336*4882a593Smuzhiyun rthr = MLAN_RTS_MAX_VALUE;
1337*4882a593Smuzhiyun } else {
1338*4882a593Smuzhiyun if (rthr < MLAN_RTS_MIN_VALUE || rthr > MLAN_RTS_MAX_VALUE) {
1339*4882a593Smuzhiyun ret = -EINVAL;
1340*4882a593Smuzhiyun goto done;
1341*4882a593Smuzhiyun }
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1345*4882a593Smuzhiyun woal_set_get_rts(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &rthr)) {
1346*4882a593Smuzhiyun ret = -EFAULT;
1347*4882a593Smuzhiyun goto done;
1348*4882a593Smuzhiyun }
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun done:
1351*4882a593Smuzhiyun LEAVE();
1352*4882a593Smuzhiyun return ret;
1353*4882a593Smuzhiyun }
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun /**
1356*4882a593Smuzhiyun * @brief Get RTS threshold
1357*4882a593Smuzhiyun *
1358*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1359*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1360*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1361*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1362*4882a593Smuzhiyun *
1363*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1364*4882a593Smuzhiyun */
woal_get_rts(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1365*4882a593Smuzhiyun static int woal_get_rts(struct net_device *dev, struct iw_request_info *info,
1366*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1367*4882a593Smuzhiyun {
1368*4882a593Smuzhiyun int rthr, ret = 0;
1369*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun ENTER();
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1374*4882a593Smuzhiyun woal_set_get_rts(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &rthr)) {
1375*4882a593Smuzhiyun ret = -EFAULT;
1376*4882a593Smuzhiyun goto done;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun vwrq->value = rthr;
1380*4882a593Smuzhiyun vwrq->disabled = ((vwrq->value < MLAN_RTS_MIN_VALUE) ||
1381*4882a593Smuzhiyun (vwrq->value > MLAN_RTS_MAX_VALUE));
1382*4882a593Smuzhiyun vwrq->fixed = 1;
1383*4882a593Smuzhiyun
1384*4882a593Smuzhiyun done:
1385*4882a593Smuzhiyun LEAVE();
1386*4882a593Smuzhiyun return ret;
1387*4882a593Smuzhiyun }
1388*4882a593Smuzhiyun
1389*4882a593Smuzhiyun /**
1390*4882a593Smuzhiyun * @brief Set Fragment threshold
1391*4882a593Smuzhiyun *
1392*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1393*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1394*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1395*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1396*4882a593Smuzhiyun *
1397*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1398*4882a593Smuzhiyun */
woal_set_frag(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1399*4882a593Smuzhiyun static int woal_set_frag(struct net_device *dev, struct iw_request_info *info,
1400*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1401*4882a593Smuzhiyun {
1402*4882a593Smuzhiyun int ret = 0;
1403*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1404*4882a593Smuzhiyun int fthr = vwrq->value;
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun ENTER();
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun if (vwrq->disabled) {
1409*4882a593Smuzhiyun fthr = MLAN_FRAG_MAX_VALUE;
1410*4882a593Smuzhiyun } else {
1411*4882a593Smuzhiyun if (fthr < MLAN_FRAG_MIN_VALUE || fthr > MLAN_FRAG_MAX_VALUE) {
1412*4882a593Smuzhiyun ret = -EINVAL;
1413*4882a593Smuzhiyun goto done;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1418*4882a593Smuzhiyun woal_set_get_frag(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &fthr)) {
1419*4882a593Smuzhiyun ret = -EFAULT;
1420*4882a593Smuzhiyun goto done;
1421*4882a593Smuzhiyun }
1422*4882a593Smuzhiyun
1423*4882a593Smuzhiyun done:
1424*4882a593Smuzhiyun LEAVE();
1425*4882a593Smuzhiyun return ret;
1426*4882a593Smuzhiyun }
1427*4882a593Smuzhiyun
1428*4882a593Smuzhiyun /**
1429*4882a593Smuzhiyun * @brief Get Fragment threshold
1430*4882a593Smuzhiyun *
1431*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1432*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1433*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1434*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1435*4882a593Smuzhiyun *
1436*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1437*4882a593Smuzhiyun */
woal_get_frag(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1438*4882a593Smuzhiyun static int woal_get_frag(struct net_device *dev, struct iw_request_info *info,
1439*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1440*4882a593Smuzhiyun {
1441*4882a593Smuzhiyun int ret = 0, fthr;
1442*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1443*4882a593Smuzhiyun
1444*4882a593Smuzhiyun ENTER();
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1447*4882a593Smuzhiyun woal_set_get_frag(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &fthr)) {
1448*4882a593Smuzhiyun ret = -EFAULT;
1449*4882a593Smuzhiyun goto done;
1450*4882a593Smuzhiyun }
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun vwrq->value = fthr;
1453*4882a593Smuzhiyun vwrq->disabled = ((vwrq->value < MLAN_FRAG_MIN_VALUE) ||
1454*4882a593Smuzhiyun (vwrq->value > MLAN_FRAG_MAX_VALUE));
1455*4882a593Smuzhiyun vwrq->fixed = 1;
1456*4882a593Smuzhiyun
1457*4882a593Smuzhiyun done:
1458*4882a593Smuzhiyun LEAVE();
1459*4882a593Smuzhiyun return ret;
1460*4882a593Smuzhiyun }
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun #if (WIRELESS_EXT >= 18)
1463*4882a593Smuzhiyun /**
1464*4882a593Smuzhiyun * @brief Get IE
1465*4882a593Smuzhiyun *
1466*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1467*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1468*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1469*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1470*4882a593Smuzhiyun *
1471*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1472*4882a593Smuzhiyun */
woal_get_gen_ie(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1473*4882a593Smuzhiyun static int woal_get_gen_ie(struct net_device *dev, struct iw_request_info *info,
1474*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1475*4882a593Smuzhiyun {
1476*4882a593Smuzhiyun int ret = 0;
1477*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1478*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
1479*4882a593Smuzhiyun int copy_size = 0, ie_len;
1480*4882a593Smuzhiyun t_u8 ie[MAX_IE_SIZE];
1481*4882a593Smuzhiyun
1482*4882a593Smuzhiyun ENTER();
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_gen_ie(priv, MLAN_ACT_GET, ie,
1485*4882a593Smuzhiyun &ie_len,
1486*4882a593Smuzhiyun MOAL_IOCTL_WAIT)) {
1487*4882a593Smuzhiyun ret = -EFAULT;
1488*4882a593Smuzhiyun goto done;
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun copy_size = MIN(ie_len, dwrq->length);
1492*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, extra, ie, copy_size, copy_size);
1493*4882a593Smuzhiyun dwrq->length = copy_size;
1494*4882a593Smuzhiyun
1495*4882a593Smuzhiyun done:
1496*4882a593Smuzhiyun LEAVE();
1497*4882a593Smuzhiyun return ret;
1498*4882a593Smuzhiyun }
1499*4882a593Smuzhiyun
1500*4882a593Smuzhiyun /**
1501*4882a593Smuzhiyun * @brief Set IE
1502*4882a593Smuzhiyun *
1503*4882a593Smuzhiyun * Pass an opaque block of data, expected to be IEEE IEs, to the driver
1504*4882a593Smuzhiyun * for eventual passthrough to the firmware in an associate/join
1505*4882a593Smuzhiyun * (and potentially start) command.
1506*4882a593Smuzhiyun *
1507*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1508*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1509*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1510*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1511*4882a593Smuzhiyun *
1512*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1513*4882a593Smuzhiyun */
woal_set_gen_ie(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1514*4882a593Smuzhiyun static int woal_set_gen_ie(struct net_device *dev, struct iw_request_info *info,
1515*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1516*4882a593Smuzhiyun {
1517*4882a593Smuzhiyun int ret = 0;
1518*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1519*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
1520*4882a593Smuzhiyun int ie_len = dwrq->length;
1521*4882a593Smuzhiyun const t_u8 wps_oui[] = {0x00, 0x50, 0xf2, 0x04};
1522*4882a593Smuzhiyun mlan_ds_wps_cfg *pwps = NULL;
1523*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
1524*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun ENTER();
1527*4882a593Smuzhiyun
1528*4882a593Smuzhiyun /* extra + 2 to skip element id and length */
1529*4882a593Smuzhiyun if (!memcmp((t_u8 *)(extra + 2), wps_oui, sizeof(wps_oui))) {
1530*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg));
1531*4882a593Smuzhiyun if (req == NULL) {
1532*4882a593Smuzhiyun ret = -ENOMEM;
1533*4882a593Smuzhiyun goto done;
1534*4882a593Smuzhiyun }
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun pwps = (mlan_ds_wps_cfg *)req->pbuf;
1537*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_WPS_CFG;
1538*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
1539*4882a593Smuzhiyun pwps->sub_command = MLAN_OID_WPS_CFG_SESSION;
1540*4882a593Smuzhiyun pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START;
1541*4882a593Smuzhiyun
1542*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1543*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
1544*4882a593Smuzhiyun ret = -EFAULT;
1545*4882a593Smuzhiyun goto done;
1546*4882a593Smuzhiyun }
1547*4882a593Smuzhiyun }
1548*4882a593Smuzhiyun
1549*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_get_gen_ie(priv, MLAN_ACT_SET,
1550*4882a593Smuzhiyun (t_u8 *)extra, &ie_len,
1551*4882a593Smuzhiyun MOAL_IOCTL_WAIT)) {
1552*4882a593Smuzhiyun ret = -EFAULT;
1553*4882a593Smuzhiyun goto done;
1554*4882a593Smuzhiyun }
1555*4882a593Smuzhiyun
1556*4882a593Smuzhiyun done:
1557*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1558*4882a593Smuzhiyun kfree(req);
1559*4882a593Smuzhiyun
1560*4882a593Smuzhiyun LEAVE();
1561*4882a593Smuzhiyun return ret;
1562*4882a593Smuzhiyun }
1563*4882a593Smuzhiyun
1564*4882a593Smuzhiyun /**
1565*4882a593Smuzhiyun * @brief Extended version of encoding configuration
1566*4882a593Smuzhiyun *
1567*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1568*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1569*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1570*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1571*4882a593Smuzhiyun *
1572*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1573*4882a593Smuzhiyun */
woal_set_encode_ext(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1574*4882a593Smuzhiyun static int woal_set_encode_ext(struct net_device *dev,
1575*4882a593Smuzhiyun struct iw_request_info *info,
1576*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1577*4882a593Smuzhiyun {
1578*4882a593Smuzhiyun struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1579*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1580*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
1581*4882a593Smuzhiyun int key_index;
1582*4882a593Smuzhiyun t_u8 *pkey_material = NULL;
1583*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
1584*4882a593Smuzhiyun mlan_ds_sec_cfg *sec = NULL;
1585*4882a593Smuzhiyun int ret = 0;
1586*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun ENTER();
1589*4882a593Smuzhiyun key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1590*4882a593Smuzhiyun if (key_index < 0 || key_index > 5) {
1591*4882a593Smuzhiyun ret = -EINVAL;
1592*4882a593Smuzhiyun goto done;
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) {
1595*4882a593Smuzhiyun ret = -EINVAL;
1596*4882a593Smuzhiyun goto done;
1597*4882a593Smuzhiyun }
1598*4882a593Smuzhiyun if (ext->key_len > (MLAN_MAX_KEY_LENGTH)) {
1599*4882a593Smuzhiyun ret = -EINVAL;
1600*4882a593Smuzhiyun goto done;
1601*4882a593Smuzhiyun }
1602*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg));
1603*4882a593Smuzhiyun if (req == NULL) {
1604*4882a593Smuzhiyun ret = -ENOMEM;
1605*4882a593Smuzhiyun goto done;
1606*4882a593Smuzhiyun }
1607*4882a593Smuzhiyun sec = (mlan_ds_sec_cfg *)req->pbuf;
1608*4882a593Smuzhiyun sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY;
1609*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_SEC_CFG;
1610*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
1611*4882a593Smuzhiyun pkey_material = (t_u8 *)(ext + 1);
1612*4882a593Smuzhiyun sec->param.encrypt_key.key_len = ext->key_len;
1613*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, sec->param.encrypt_key.mac_addr,
1614*4882a593Smuzhiyun (u8 *)ext->addr.sa_data, ETH_ALEN,
1615*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.mac_addr));
1616*4882a593Smuzhiyun /* Disable and Remove Key */
1617*4882a593Smuzhiyun if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) {
1618*4882a593Smuzhiyun sec->param.encrypt_key.key_remove = MTRUE;
1619*4882a593Smuzhiyun sec->param.encrypt_key.key_index = key_index;
1620*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY;
1621*4882a593Smuzhiyun PRINTM(MIOCTL,
1622*4882a593Smuzhiyun "Remove key key_index=%d, dwrq->flags=0x%x " MACSTR "\n",
1623*4882a593Smuzhiyun key_index, dwrq->flags,
1624*4882a593Smuzhiyun MAC2STR(sec->param.encrypt_key.mac_addr));
1625*4882a593Smuzhiyun } else if (ext->key_len <= MAX_WEP_KEY_SIZE) {
1626*4882a593Smuzhiyun /* Set WEP key */
1627*4882a593Smuzhiyun sec->param.encrypt_key.key_index = key_index;
1628*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = ext->ext_flags;
1629*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
1630*4882a593Smuzhiyun sec->param.encrypt_key.key_material,
1631*4882a593Smuzhiyun pkey_material, ext->key_len,
1632*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.key_material));
1633*4882a593Smuzhiyun if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1634*4882a593Smuzhiyun sec->param.encrypt_key.is_current_wep_key = MTRUE;
1635*4882a593Smuzhiyun } else {
1636*4882a593Smuzhiyun /* Set WPA key */
1637*4882a593Smuzhiyun sec->param.encrypt_key.key_index = key_index;
1638*4882a593Smuzhiyun sec->param.encrypt_key.key_flags = ext->ext_flags;
1639*4882a593Smuzhiyun if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1640*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
1641*4882a593Smuzhiyun sec->param.encrypt_key.pn,
1642*4882a593Smuzhiyun (t_u8 *)ext->rx_seq, SEQ_MAX_SIZE,
1643*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.pn));
1644*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "Rx PN", sec->param.encrypt_key.pn,
1645*4882a593Smuzhiyun SEQ_MAX_SIZE);
1646*4882a593Smuzhiyun }
1647*4882a593Smuzhiyun if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) {
1648*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
1649*4882a593Smuzhiyun sec->param.encrypt_key.pn,
1650*4882a593Smuzhiyun (t_u8 *)ext->tx_seq, SEQ_MAX_SIZE,
1651*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.pn));
1652*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "Tx PN", sec->param.encrypt_key.pn,
1653*4882a593Smuzhiyun SEQ_MAX_SIZE);
1654*4882a593Smuzhiyun }
1655*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
1656*4882a593Smuzhiyun sec->param.encrypt_key.key_material,
1657*4882a593Smuzhiyun pkey_material, ext->key_len,
1658*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.key_material));
1659*4882a593Smuzhiyun PRINTM(MIOCTL,
1660*4882a593Smuzhiyun "set wpa key key_index=%d, key_len=%d key_flags=0x%x " MACSTR
1661*4882a593Smuzhiyun "\n",
1662*4882a593Smuzhiyun key_index, ext->key_len,
1663*4882a593Smuzhiyun sec->param.encrypt_key.key_flags,
1664*4882a593Smuzhiyun MAC2STR(sec->param.encrypt_key.mac_addr));
1665*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "wpa key", pkey_material, ext->key_len);
1666*4882a593Smuzhiyun #define IW_ENCODE_ALG_AES_CMAC 5
1667*4882a593Smuzhiyun if (ext->alg == IW_ENCODE_ALG_AES_CMAC)
1668*4882a593Smuzhiyun sec->param.encrypt_key.key_flags |=
1669*4882a593Smuzhiyun KEY_FLAG_AES_MCAST_IGTK;
1670*4882a593Smuzhiyun #define IW_ENCODE_ALG_SMS4 0x20
1671*4882a593Smuzhiyun /* Set WAPI key */
1672*4882a593Smuzhiyun if (ext->alg == IW_ENCODE_ALG_SMS4) {
1673*4882a593Smuzhiyun sec->param.encrypt_key.is_wapi_key = MTRUE;
1674*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle,
1675*4882a593Smuzhiyun sec->param.encrypt_key.pn,
1676*4882a593Smuzhiyun (t_u8 *)ext->tx_seq, SEQ_MAX_SIZE,
1677*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.pn));
1678*4882a593Smuzhiyun moal_memcpy_ext(
1679*4882a593Smuzhiyun priv->phandle,
1680*4882a593Smuzhiyun &sec->param.encrypt_key.pn[SEQ_MAX_SIZE],
1681*4882a593Smuzhiyun (t_u8 *)ext->rx_seq, SEQ_MAX_SIZE,
1682*4882a593Smuzhiyun sizeof(sec->param.encrypt_key.pn) -
1683*4882a593Smuzhiyun SEQ_MAX_SIZE);
1684*4882a593Smuzhiyun DBG_HEXDUMP(MCMD_D, "WAPI PN",
1685*4882a593Smuzhiyun sec->param.encrypt_key.pn, PN_SIZE);
1686*4882a593Smuzhiyun }
1687*4882a593Smuzhiyun }
1688*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1689*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS)
1690*4882a593Smuzhiyun ret = -EFAULT;
1691*4882a593Smuzhiyun done:
1692*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
1693*4882a593Smuzhiyun kfree(req);
1694*4882a593Smuzhiyun LEAVE();
1695*4882a593Smuzhiyun return ret;
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
1698*4882a593Smuzhiyun /**
1699*4882a593Smuzhiyun * @brief Extended version of encoding configuration
1700*4882a593Smuzhiyun *
1701*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1702*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1703*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1704*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1705*4882a593Smuzhiyun *
1706*4882a593Smuzhiyun * @return -EOPNOTSUPP
1707*4882a593Smuzhiyun */
woal_get_encode_ext(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1708*4882a593Smuzhiyun static int woal_get_encode_ext(struct net_device *dev,
1709*4882a593Smuzhiyun struct iw_request_info *info,
1710*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1711*4882a593Smuzhiyun {
1712*4882a593Smuzhiyun ENTER();
1713*4882a593Smuzhiyun LEAVE();
1714*4882a593Smuzhiyun return -EOPNOTSUPP;
1715*4882a593Smuzhiyun }
1716*4882a593Smuzhiyun
1717*4882a593Smuzhiyun /**
1718*4882a593Smuzhiyun * @brief Request MLME operation
1719*4882a593Smuzhiyun *
1720*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1721*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1722*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1723*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1724*4882a593Smuzhiyun *
1725*4882a593Smuzhiyun * @return 0--success, otherwise fail
1726*4882a593Smuzhiyun */
woal_set_mlme(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1727*4882a593Smuzhiyun static int woal_set_mlme(struct net_device *dev, struct iw_request_info *info,
1728*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1729*4882a593Smuzhiyun {
1730*4882a593Smuzhiyun struct iw_mlme *mlme = (struct iw_mlme *)extra;
1731*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1732*4882a593Smuzhiyun int ret = 0;
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun ENTER();
1735*4882a593Smuzhiyun if ((mlme->cmd == IW_MLME_DEAUTH) || (mlme->cmd == IW_MLME_DISASSOC)) {
1736*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1737*4882a593Smuzhiyun woal_disconnect(priv, MOAL_IOCTL_WAIT,
1738*4882a593Smuzhiyun (t_u8 *)mlme->addr.sa_data,
1739*4882a593Smuzhiyun DEF_DEAUTH_REASON_CODE))
1740*4882a593Smuzhiyun ret = -EFAULT;
1741*4882a593Smuzhiyun }
1742*4882a593Smuzhiyun LEAVE();
1743*4882a593Smuzhiyun return ret;
1744*4882a593Smuzhiyun }
1745*4882a593Smuzhiyun
1746*4882a593Smuzhiyun /** @brief Set authentication mode parameters
1747*4882a593Smuzhiyun *
1748*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1749*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1750*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1751*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1752*4882a593Smuzhiyun *
1753*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1754*4882a593Smuzhiyun */
woal_set_auth(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1755*4882a593Smuzhiyun static int woal_set_auth(struct net_device *dev, struct iw_request_info *info,
1756*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1757*4882a593Smuzhiyun {
1758*4882a593Smuzhiyun int ret = 0;
1759*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1760*4882a593Smuzhiyun struct iw_param *vwrq = &wrqu->param;
1761*4882a593Smuzhiyun t_u32 auth_mode = 0;
1762*4882a593Smuzhiyun t_u32 encrypt_mode = 0;
1763*4882a593Smuzhiyun ENTER();
1764*4882a593Smuzhiyun
1765*4882a593Smuzhiyun switch (vwrq->flags & IW_AUTH_INDEX) {
1766*4882a593Smuzhiyun case IW_AUTH_CIPHER_PAIRWISE:
1767*4882a593Smuzhiyun case IW_AUTH_CIPHER_GROUP:
1768*4882a593Smuzhiyun if (vwrq->value & IW_AUTH_CIPHER_NONE)
1769*4882a593Smuzhiyun encrypt_mode = MLAN_ENCRYPTION_MODE_NONE;
1770*4882a593Smuzhiyun else if (vwrq->value & IW_AUTH_CIPHER_WEP40)
1771*4882a593Smuzhiyun encrypt_mode = MLAN_ENCRYPTION_MODE_WEP40;
1772*4882a593Smuzhiyun else if (vwrq->value & IW_AUTH_CIPHER_WEP104)
1773*4882a593Smuzhiyun encrypt_mode = MLAN_ENCRYPTION_MODE_WEP104;
1774*4882a593Smuzhiyun else if (vwrq->value & IW_AUTH_CIPHER_TKIP)
1775*4882a593Smuzhiyun encrypt_mode = MLAN_ENCRYPTION_MODE_TKIP;
1776*4882a593Smuzhiyun else if (vwrq->value & IW_AUTH_CIPHER_CCMP)
1777*4882a593Smuzhiyun encrypt_mode = MLAN_ENCRYPTION_MODE_CCMP;
1778*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1779*4882a593Smuzhiyun woal_set_encrypt_mode(priv, MOAL_IOCTL_WAIT, encrypt_mode))
1780*4882a593Smuzhiyun ret = -EFAULT;
1781*4882a593Smuzhiyun break;
1782*4882a593Smuzhiyun case IW_AUTH_80211_AUTH_ALG:
1783*4882a593Smuzhiyun switch (vwrq->value) {
1784*4882a593Smuzhiyun case IW_AUTH_ALG_SHARED_KEY:
1785*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode shared key!\n");
1786*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_SHARED;
1787*4882a593Smuzhiyun break;
1788*4882a593Smuzhiyun case IW_AUTH_ALG_LEAP:
1789*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode LEAP!\n");
1790*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_NETWORKEAP;
1791*4882a593Smuzhiyun break;
1792*4882a593Smuzhiyun case IW_AUTH_ALG_OPEN_SYSTEM:
1793*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode open!\n");
1794*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_OPEN;
1795*4882a593Smuzhiyun break;
1796*4882a593Smuzhiyun case IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM:
1797*4882a593Smuzhiyun default:
1798*4882a593Smuzhiyun PRINTM(MINFO, "Auth mode auto!\n");
1799*4882a593Smuzhiyun auth_mode = MLAN_AUTH_MODE_AUTO;
1800*4882a593Smuzhiyun break;
1801*4882a593Smuzhiyun }
1802*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1803*4882a593Smuzhiyun woal_set_auth_mode(priv, MOAL_IOCTL_WAIT, auth_mode))
1804*4882a593Smuzhiyun ret = -EFAULT;
1805*4882a593Smuzhiyun break;
1806*4882a593Smuzhiyun case IW_AUTH_WPA_ENABLED:
1807*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1808*4882a593Smuzhiyun woal_set_wpa_enable(priv, MOAL_IOCTL_WAIT, vwrq->value))
1809*4882a593Smuzhiyun ret = -EFAULT;
1810*4882a593Smuzhiyun break;
1811*4882a593Smuzhiyun #define IW_AUTH_WAPI_ENABLED 0x20
1812*4882a593Smuzhiyun case IW_AUTH_WAPI_ENABLED:
1813*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1814*4882a593Smuzhiyun woal_set_wapi_enable(priv, MOAL_IOCTL_WAIT, vwrq->value))
1815*4882a593Smuzhiyun ret = -EFAULT;
1816*4882a593Smuzhiyun break;
1817*4882a593Smuzhiyun case IW_AUTH_WPA_VERSION:
1818*4882a593Smuzhiyun /* set WPA_VERSION_DISABLED/VERSION_WPA/VERSION_WP2 */
1819*4882a593Smuzhiyun priv->wpa_version = vwrq->value;
1820*4882a593Smuzhiyun break;
1821*4882a593Smuzhiyun case IW_AUTH_KEY_MGMT:
1822*4882a593Smuzhiyun /* set KEY_MGMT_802_1X/KEY_MGMT_PSK */
1823*4882a593Smuzhiyun priv->key_mgmt = vwrq->value;
1824*4882a593Smuzhiyun break;
1825*4882a593Smuzhiyun case IW_AUTH_TKIP_COUNTERMEASURES:
1826*4882a593Smuzhiyun case IW_AUTH_DROP_UNENCRYPTED:
1827*4882a593Smuzhiyun case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1828*4882a593Smuzhiyun case IW_AUTH_ROAMING_CONTROL:
1829*4882a593Smuzhiyun case IW_AUTH_PRIVACY_INVOKED:
1830*4882a593Smuzhiyun #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1831*4882a593Smuzhiyun case IW_AUTH_MFP:
1832*4882a593Smuzhiyun #endif
1833*4882a593Smuzhiyun break;
1834*4882a593Smuzhiyun default:
1835*4882a593Smuzhiyun ret = -EOPNOTSUPP;
1836*4882a593Smuzhiyun break;
1837*4882a593Smuzhiyun }
1838*4882a593Smuzhiyun LEAVE();
1839*4882a593Smuzhiyun return ret;
1840*4882a593Smuzhiyun }
1841*4882a593Smuzhiyun
1842*4882a593Smuzhiyun /**
1843*4882a593Smuzhiyun * @brief Get authentication mode parameters
1844*4882a593Smuzhiyun *
1845*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1846*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1847*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1848*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1849*4882a593Smuzhiyun *
1850*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1851*4882a593Smuzhiyun */
woal_get_auth(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1852*4882a593Smuzhiyun static int woal_get_auth(struct net_device *dev, struct iw_request_info *info,
1853*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1854*4882a593Smuzhiyun {
1855*4882a593Smuzhiyun int ret = 0;
1856*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1857*4882a593Smuzhiyun struct iw_param *vwrq = &wrqu->param;
1858*4882a593Smuzhiyun t_u32 encrypt_mode = 0;
1859*4882a593Smuzhiyun t_u32 auth_mode;
1860*4882a593Smuzhiyun t_u32 wpa_enable;
1861*4882a593Smuzhiyun ENTER();
1862*4882a593Smuzhiyun switch (vwrq->flags & IW_AUTH_INDEX) {
1863*4882a593Smuzhiyun case IW_AUTH_CIPHER_PAIRWISE:
1864*4882a593Smuzhiyun case IW_AUTH_CIPHER_GROUP:
1865*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1866*4882a593Smuzhiyun woal_get_encrypt_mode(priv, MOAL_IOCTL_WAIT, &encrypt_mode))
1867*4882a593Smuzhiyun ret = -EFAULT;
1868*4882a593Smuzhiyun else {
1869*4882a593Smuzhiyun if (encrypt_mode == MLAN_ENCRYPTION_MODE_NONE)
1870*4882a593Smuzhiyun vwrq->value = IW_AUTH_CIPHER_NONE;
1871*4882a593Smuzhiyun else if (encrypt_mode == MLAN_ENCRYPTION_MODE_WEP40)
1872*4882a593Smuzhiyun vwrq->value = IW_AUTH_CIPHER_WEP40;
1873*4882a593Smuzhiyun else if (encrypt_mode == MLAN_ENCRYPTION_MODE_TKIP)
1874*4882a593Smuzhiyun vwrq->value = IW_AUTH_CIPHER_TKIP;
1875*4882a593Smuzhiyun else if (encrypt_mode == MLAN_ENCRYPTION_MODE_CCMP)
1876*4882a593Smuzhiyun vwrq->value = IW_AUTH_CIPHER_CCMP;
1877*4882a593Smuzhiyun else if (encrypt_mode == MLAN_ENCRYPTION_MODE_WEP104)
1878*4882a593Smuzhiyun vwrq->value = IW_AUTH_CIPHER_WEP104;
1879*4882a593Smuzhiyun }
1880*4882a593Smuzhiyun break;
1881*4882a593Smuzhiyun case IW_AUTH_80211_AUTH_ALG:
1882*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1883*4882a593Smuzhiyun woal_get_auth_mode(priv, MOAL_IOCTL_WAIT, &auth_mode))
1884*4882a593Smuzhiyun ret = -EFAULT;
1885*4882a593Smuzhiyun else {
1886*4882a593Smuzhiyun if (auth_mode == MLAN_AUTH_MODE_SHARED)
1887*4882a593Smuzhiyun vwrq->value = IW_AUTH_ALG_SHARED_KEY;
1888*4882a593Smuzhiyun else if (auth_mode == MLAN_AUTH_MODE_NETWORKEAP)
1889*4882a593Smuzhiyun vwrq->value = IW_AUTH_ALG_LEAP;
1890*4882a593Smuzhiyun else
1891*4882a593Smuzhiyun vwrq->value = IW_AUTH_ALG_OPEN_SYSTEM;
1892*4882a593Smuzhiyun }
1893*4882a593Smuzhiyun break;
1894*4882a593Smuzhiyun case IW_AUTH_WPA_ENABLED:
1895*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
1896*4882a593Smuzhiyun woal_get_wpa_enable(priv, MOAL_IOCTL_WAIT, &wpa_enable))
1897*4882a593Smuzhiyun ret = -EFAULT;
1898*4882a593Smuzhiyun else
1899*4882a593Smuzhiyun vwrq->value = wpa_enable;
1900*4882a593Smuzhiyun break;
1901*4882a593Smuzhiyun case IW_AUTH_WPA_VERSION:
1902*4882a593Smuzhiyun vwrq->value = priv->wpa_version;
1903*4882a593Smuzhiyun break;
1904*4882a593Smuzhiyun case IW_AUTH_KEY_MGMT:
1905*4882a593Smuzhiyun vwrq->value = priv->key_mgmt;
1906*4882a593Smuzhiyun break;
1907*4882a593Smuzhiyun case IW_AUTH_TKIP_COUNTERMEASURES:
1908*4882a593Smuzhiyun case IW_AUTH_DROP_UNENCRYPTED:
1909*4882a593Smuzhiyun case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1910*4882a593Smuzhiyun case IW_AUTH_ROAMING_CONTROL:
1911*4882a593Smuzhiyun case IW_AUTH_PRIVACY_INVOKED:
1912*4882a593Smuzhiyun default:
1913*4882a593Smuzhiyun ret = -EOPNOTSUPP;
1914*4882a593Smuzhiyun goto done;
1915*4882a593Smuzhiyun }
1916*4882a593Smuzhiyun
1917*4882a593Smuzhiyun done:
1918*4882a593Smuzhiyun LEAVE();
1919*4882a593Smuzhiyun return ret;
1920*4882a593Smuzhiyun }
1921*4882a593Smuzhiyun
1922*4882a593Smuzhiyun /**
1923*4882a593Smuzhiyun * @brief Set PMKSA Cache
1924*4882a593Smuzhiyun *
1925*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1926*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1927*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
1928*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1929*4882a593Smuzhiyun *
1930*4882a593Smuzhiyun * @return -EOPNOTSUPP
1931*4882a593Smuzhiyun */
woal_set_pmksa(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)1932*4882a593Smuzhiyun static int woal_set_pmksa(struct net_device *dev, struct iw_request_info *info,
1933*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
1934*4882a593Smuzhiyun {
1935*4882a593Smuzhiyun ENTER();
1936*4882a593Smuzhiyun LEAVE();
1937*4882a593Smuzhiyun return -EOPNOTSUPP;
1938*4882a593Smuzhiyun }
1939*4882a593Smuzhiyun
1940*4882a593Smuzhiyun #endif /* WE >= 18 */
1941*4882a593Smuzhiyun
1942*4882a593Smuzhiyun /* Data rate listing
1943*4882a593Smuzhiyun * MULTI_BANDS:
1944*4882a593Smuzhiyun * abg a b b/g
1945*4882a593Smuzhiyun * Infra G(12) A(8) B(4) G(12)
1946*4882a593Smuzhiyun * Adhoc A+B(12) A(8) B(4) B(4)
1947*4882a593Smuzhiyun * non-MULTI_BANDS:
1948*4882a593Smuzhiyun b b/g
1949*4882a593Smuzhiyun * Infra B(4) G(12)
1950*4882a593Smuzhiyun * Adhoc B(4) B(4)
1951*4882a593Smuzhiyun */
1952*4882a593Smuzhiyun /**
1953*4882a593Smuzhiyun * @brief Get Range Info
1954*4882a593Smuzhiyun *
1955*4882a593Smuzhiyun * @param dev A pointer to net_device structure
1956*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
1957*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
1958*4882a593Smuzhiyun * @param extra A pointer to extra data buf
1959*4882a593Smuzhiyun *
1960*4882a593Smuzhiyun * @return 0 --success, otherwise fail
1961*4882a593Smuzhiyun */
woal_get_range(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)1962*4882a593Smuzhiyun static int woal_get_range(struct net_device *dev, struct iw_request_info *info,
1963*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
1964*4882a593Smuzhiyun {
1965*4882a593Smuzhiyun int i;
1966*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
1967*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
1968*4882a593Smuzhiyun struct iw_range *range = (struct iw_range *)extra;
1969*4882a593Smuzhiyun moal_802_11_rates rates;
1970*4882a593Smuzhiyun mlan_chan_list *pchan_list = NULL;
1971*4882a593Smuzhiyun mlan_bss_info bss_info;
1972*4882a593Smuzhiyun gfp_t flag;
1973*4882a593Smuzhiyun
1974*4882a593Smuzhiyun ENTER();
1975*4882a593Smuzhiyun
1976*4882a593Smuzhiyun flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
1977*4882a593Smuzhiyun pchan_list = kzalloc(sizeof(mlan_chan_list), flag);
1978*4882a593Smuzhiyun if (!pchan_list) {
1979*4882a593Smuzhiyun LEAVE();
1980*4882a593Smuzhiyun return -ENOMEM;
1981*4882a593Smuzhiyun }
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun dwrq->length = sizeof(struct iw_range);
1984*4882a593Smuzhiyun memset(range, 0, sizeof(struct iw_range));
1985*4882a593Smuzhiyun
1986*4882a593Smuzhiyun range->min_nwid = 0;
1987*4882a593Smuzhiyun range->max_nwid = 0;
1988*4882a593Smuzhiyun
1989*4882a593Smuzhiyun memset(&rates, 0, sizeof(rates));
1990*4882a593Smuzhiyun woal_get_data_rates(priv, MOAL_IOCTL_WAIT, &rates);
1991*4882a593Smuzhiyun range->num_bitrates = rates.num_of_rates;
1992*4882a593Smuzhiyun
1993*4882a593Smuzhiyun for (i = 0;
1994*4882a593Smuzhiyun i < MIN(range->num_bitrates, IW_MAX_BITRATES) && rates.rates[i];
1995*4882a593Smuzhiyun i++) {
1996*4882a593Smuzhiyun range->bitrate[i] = (rates.rates[i] & 0x7f) * 500000;
1997*4882a593Smuzhiyun }
1998*4882a593Smuzhiyun range->num_bitrates = i;
1999*4882a593Smuzhiyun PRINTM(MINFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
2000*4882a593Smuzhiyun range->num_bitrates);
2001*4882a593Smuzhiyun
2002*4882a593Smuzhiyun range->num_frequency = 0;
2003*4882a593Smuzhiyun
2004*4882a593Smuzhiyun woal_get_channel_list(priv, MOAL_IOCTL_WAIT, pchan_list);
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyun range->num_frequency = MIN(pchan_list->num_of_chan, IW_MAX_FREQUENCIES);
2007*4882a593Smuzhiyun
2008*4882a593Smuzhiyun for (i = 0; i < range->num_frequency; i++) {
2009*4882a593Smuzhiyun range->freq[i].i = (long)pchan_list->cf[i].channel;
2010*4882a593Smuzhiyun range->freq[i].m = (long)pchan_list->cf[i].freq * 100000;
2011*4882a593Smuzhiyun range->freq[i].e = 1;
2012*4882a593Smuzhiyun }
2013*4882a593Smuzhiyun kfree(pchan_list);
2014*4882a593Smuzhiyun
2015*4882a593Smuzhiyun PRINTM(MINFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
2016*4882a593Smuzhiyun IW_MAX_FREQUENCIES, range->num_frequency);
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun range->num_channels = range->num_frequency;
2019*4882a593Smuzhiyun
2020*4882a593Smuzhiyun woal_sort_channels(&range->freq[0], range->num_frequency);
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun /*
2023*4882a593Smuzhiyun * Set an indication of the max TCP throughput in bit/s that we can
2024*4882a593Smuzhiyun * expect using this interface
2025*4882a593Smuzhiyun */
2026*4882a593Smuzhiyun if (i > 2)
2027*4882a593Smuzhiyun range->throughput = 5000 * 1000;
2028*4882a593Smuzhiyun else
2029*4882a593Smuzhiyun range->throughput = 1500 * 1000;
2030*4882a593Smuzhiyun
2031*4882a593Smuzhiyun range->min_rts = MLAN_RTS_MIN_VALUE;
2032*4882a593Smuzhiyun range->max_rts = MLAN_RTS_MAX_VALUE;
2033*4882a593Smuzhiyun range->min_frag = MLAN_FRAG_MIN_VALUE;
2034*4882a593Smuzhiyun range->max_frag = MLAN_FRAG_MAX_VALUE;
2035*4882a593Smuzhiyun
2036*4882a593Smuzhiyun range->encoding_size[0] = 5;
2037*4882a593Smuzhiyun range->encoding_size[1] = 13;
2038*4882a593Smuzhiyun range->num_encoding_sizes = 2;
2039*4882a593Smuzhiyun range->max_encoding_tokens = 4;
2040*4882a593Smuzhiyun
2041*4882a593Smuzhiyun /** Minimum power period */
2042*4882a593Smuzhiyun #define IW_POWER_PERIOD_MIN 1000000 /* 1 sec */
2043*4882a593Smuzhiyun /** Maximum power period */
2044*4882a593Smuzhiyun #define IW_POWER_PERIOD_MAX 120000000 /* 2 min */
2045*4882a593Smuzhiyun /** Minimum power timeout value */
2046*4882a593Smuzhiyun #define IW_POWER_TIMEOUT_MIN 1000 /* 1 ms */
2047*4882a593Smuzhiyun /** Maximim power timeout value */
2048*4882a593Smuzhiyun #define IW_POWER_TIMEOUT_MAX 1000000 /* 1 sec */
2049*4882a593Smuzhiyun
2050*4882a593Smuzhiyun /* Power Management duration & timeout */
2051*4882a593Smuzhiyun range->min_pmp = IW_POWER_PERIOD_MIN;
2052*4882a593Smuzhiyun range->max_pmp = IW_POWER_PERIOD_MAX;
2053*4882a593Smuzhiyun range->min_pmt = IW_POWER_TIMEOUT_MIN;
2054*4882a593Smuzhiyun range->max_pmt = IW_POWER_TIMEOUT_MAX;
2055*4882a593Smuzhiyun range->pmp_flags = IW_POWER_PERIOD;
2056*4882a593Smuzhiyun range->pmt_flags = IW_POWER_TIMEOUT;
2057*4882a593Smuzhiyun range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
2058*4882a593Smuzhiyun
2059*4882a593Smuzhiyun /*
2060*4882a593Smuzhiyun * Minimum version we recommend
2061*4882a593Smuzhiyun */
2062*4882a593Smuzhiyun range->we_version_source = 15;
2063*4882a593Smuzhiyun
2064*4882a593Smuzhiyun /*
2065*4882a593Smuzhiyun * Version we are compiled with
2066*4882a593Smuzhiyun */
2067*4882a593Smuzhiyun range->we_version_compiled = WIRELESS_EXT;
2068*4882a593Smuzhiyun
2069*4882a593Smuzhiyun range->retry_capa = IW_RETRY_LIMIT;
2070*4882a593Smuzhiyun range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
2071*4882a593Smuzhiyun
2072*4882a593Smuzhiyun range->min_retry = MLAN_TX_RETRY_MIN;
2073*4882a593Smuzhiyun range->max_retry = MLAN_TX_RETRY_MAX;
2074*4882a593Smuzhiyun
2075*4882a593Smuzhiyun /*
2076*4882a593Smuzhiyun * Set the qual, level and noise range values
2077*4882a593Smuzhiyun */
2078*4882a593Smuzhiyun /*
2079*4882a593Smuzhiyun * need to put the right values here
2080*4882a593Smuzhiyun */
2081*4882a593Smuzhiyun /** Maximum quality percentage */
2082*4882a593Smuzhiyun #define IW_MAX_QUAL_PERCENT 5
2083*4882a593Smuzhiyun /** Average quality percentage */
2084*4882a593Smuzhiyun #define IW_AVG_QUAL_PERCENT 3
2085*4882a593Smuzhiyun range->max_qual.qual = IW_MAX_QUAL_PERCENT;
2086*4882a593Smuzhiyun range->max_qual.level = 0;
2087*4882a593Smuzhiyun range->max_qual.noise = 0;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun range->avg_qual.qual = IW_AVG_QUAL_PERCENT;
2090*4882a593Smuzhiyun range->avg_qual.level = 0;
2091*4882a593Smuzhiyun range->avg_qual.noise = 0;
2092*4882a593Smuzhiyun
2093*4882a593Smuzhiyun range->sensitivity = 0;
2094*4882a593Smuzhiyun
2095*4882a593Smuzhiyun /*
2096*4882a593Smuzhiyun * Setup the supported power level ranges
2097*4882a593Smuzhiyun */
2098*4882a593Smuzhiyun memset(range->txpower, 0, sizeof(range->txpower));
2099*4882a593Smuzhiyun
2100*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
2101*4882a593Smuzhiyun
2102*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info);
2103*4882a593Smuzhiyun
2104*4882a593Smuzhiyun range->txpower[0] = bss_info.min_power_level;
2105*4882a593Smuzhiyun range->txpower[1] = bss_info.max_power_level;
2106*4882a593Smuzhiyun range->num_txpower = 2;
2107*4882a593Smuzhiyun range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
2108*4882a593Smuzhiyun
2109*4882a593Smuzhiyun #if (WIRELESS_EXT >= 18)
2110*4882a593Smuzhiyun range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
2111*4882a593Smuzhiyun IW_ENC_CAPA_CIPHER_CCMP | IW_ENC_CAPA_CIPHER_TKIP;
2112*4882a593Smuzhiyun #endif
2113*4882a593Smuzhiyun LEAVE();
2114*4882a593Smuzhiyun return 0;
2115*4882a593Smuzhiyun }
2116*4882a593Smuzhiyun
2117*4882a593Smuzhiyun #ifdef MEF_CFG_RX_FILTER
2118*4882a593Smuzhiyun /**
2119*4882a593Smuzhiyun * @brief Enable/disable Rx broadcast/multicast filter in non-HS mode
2120*4882a593Smuzhiyun *
2121*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
2122*4882a593Smuzhiyun * @param enable MTRUE/MFALSE: enable/disable
2123*4882a593Smuzhiyun *
2124*4882a593Smuzhiyun * @return 0 -- success, otherwise fail
2125*4882a593Smuzhiyun */
woal_set_rxfilter(moal_private * priv,BOOLEAN enable)2126*4882a593Smuzhiyun static int woal_set_rxfilter(moal_private *priv, BOOLEAN enable)
2127*4882a593Smuzhiyun {
2128*4882a593Smuzhiyun int ret = 0;
2129*4882a593Smuzhiyun mlan_ioctl_req *req = NULL;
2130*4882a593Smuzhiyun mlan_ds_misc_cfg *misc = NULL;
2131*4882a593Smuzhiyun mlan_ds_misc_mef_cfg *mef_cfg = NULL;
2132*4882a593Smuzhiyun mlan_status status = MLAN_STATUS_SUCCESS;
2133*4882a593Smuzhiyun
2134*4882a593Smuzhiyun ENTER();
2135*4882a593Smuzhiyun
2136*4882a593Smuzhiyun req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
2137*4882a593Smuzhiyun if (req == NULL) {
2138*4882a593Smuzhiyun ret = -ENOMEM;
2139*4882a593Smuzhiyun goto done;
2140*4882a593Smuzhiyun }
2141*4882a593Smuzhiyun misc = (mlan_ds_misc_cfg *)req->pbuf;
2142*4882a593Smuzhiyun mef_cfg = &misc->param.mef_cfg;
2143*4882a593Smuzhiyun req->req_id = MLAN_IOCTL_MISC_CFG;
2144*4882a593Smuzhiyun misc->sub_command = MLAN_OID_MISC_MEF_CFG;
2145*4882a593Smuzhiyun req->action = MLAN_ACT_SET;
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun mef_cfg->sub_id = (enable ? MEF_CFG_RX_FILTER_ENABLE : MEF_CFG_DISABLE);
2148*4882a593Smuzhiyun status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
2149*4882a593Smuzhiyun if (status != MLAN_STATUS_SUCCESS) {
2150*4882a593Smuzhiyun ret = -EFAULT;
2151*4882a593Smuzhiyun goto done;
2152*4882a593Smuzhiyun }
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun done:
2155*4882a593Smuzhiyun if (status != MLAN_STATUS_PENDING)
2156*4882a593Smuzhiyun kfree(req);
2157*4882a593Smuzhiyun LEAVE();
2158*4882a593Smuzhiyun return ret;
2159*4882a593Smuzhiyun }
2160*4882a593Smuzhiyun #endif
2161*4882a593Smuzhiyun
2162*4882a593Smuzhiyun /**
2163*4882a593Smuzhiyun * @brief Set priv command
2164*4882a593Smuzhiyun *
2165*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2166*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
2167*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
2168*4882a593Smuzhiyun * @param extra A pointer to extra data buf
2169*4882a593Smuzhiyun *
2170*4882a593Smuzhiyun * @return 0 --success, otherwise fail
2171*4882a593Smuzhiyun */
woal_set_priv(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2172*4882a593Smuzhiyun static int woal_set_priv(struct net_device *dev, struct iw_request_info *info,
2173*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
2174*4882a593Smuzhiyun {
2175*4882a593Smuzhiyun int ret = 0;
2176*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2177*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
2178*4882a593Smuzhiyun char *buf = NULL;
2179*4882a593Smuzhiyun int power_mode = 0;
2180*4882a593Smuzhiyun int band = 0;
2181*4882a593Smuzhiyun char *pband = NULL;
2182*4882a593Smuzhiyun mlan_bss_info bss_info;
2183*4882a593Smuzhiyun mlan_ds_get_signal signal;
2184*4882a593Smuzhiyun mlan_rate_cfg_t rate;
2185*4882a593Smuzhiyun char *pdata = NULL;
2186*4882a593Smuzhiyun t_u8 country_code[COUNTRY_CODE_LEN];
2187*4882a593Smuzhiyun int len = 0;
2188*4882a593Smuzhiyun gfp_t flag;
2189*4882a593Smuzhiyun ENTER();
2190*4882a593Smuzhiyun if (!priv || !priv->phandle) {
2191*4882a593Smuzhiyun PRINTM(MERROR, "priv or handle is NULL\n");
2192*4882a593Smuzhiyun ret = -EFAULT;
2193*4882a593Smuzhiyun goto done;
2194*4882a593Smuzhiyun }
2195*4882a593Smuzhiyun flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
2196*4882a593Smuzhiyun buf = kzalloc(dwrq->length + 1, flag);
2197*4882a593Smuzhiyun if (!buf) {
2198*4882a593Smuzhiyun ret = -ENOMEM;
2199*4882a593Smuzhiyun goto done;
2200*4882a593Smuzhiyun }
2201*4882a593Smuzhiyun if (copy_from_user(buf, dwrq->pointer, dwrq->length)) {
2202*4882a593Smuzhiyun ret = -EFAULT;
2203*4882a593Smuzhiyun goto done;
2204*4882a593Smuzhiyun }
2205*4882a593Smuzhiyun buf[dwrq->length] = '\0';
2206*4882a593Smuzhiyun PRINTM(MIOCTL, "SIOCSIWPRIV request = %s\n", buf);
2207*4882a593Smuzhiyun if (strncmp(buf, "RSSILOW-THRESHOLD", strlen("RSSILOW-THRESHOLD")) ==
2208*4882a593Smuzhiyun 0) {
2209*4882a593Smuzhiyun if (dwrq->length > strlen("RSSILOW-THRESHOLD") + 1) {
2210*4882a593Smuzhiyun pdata = buf + strlen("RSSILOW-THRESHOLD") + 1;
2211*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2212*4882a593Smuzhiyun woal_set_rssi_low_threshold(priv, pdata,
2213*4882a593Smuzhiyun MOAL_IOCTL_WAIT)) {
2214*4882a593Smuzhiyun ret = -EFAULT;
2215*4882a593Smuzhiyun goto done;
2216*4882a593Smuzhiyun }
2217*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2218*4882a593Smuzhiyun } else {
2219*4882a593Smuzhiyun ret = -EFAULT;
2220*4882a593Smuzhiyun goto done;
2221*4882a593Smuzhiyun }
2222*4882a593Smuzhiyun } else if (strncmp(buf, "RSSI", strlen("RSSI")) == 0) {
2223*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2224*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
2225*4882a593Smuzhiyun ret = -EFAULT;
2226*4882a593Smuzhiyun goto done;
2227*4882a593Smuzhiyun }
2228*4882a593Smuzhiyun if (bss_info.media_connected) {
2229*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2230*4882a593Smuzhiyun woal_get_signal_info(priv, MOAL_IOCTL_WAIT,
2231*4882a593Smuzhiyun &signal)) {
2232*4882a593Smuzhiyun ret = -EFAULT;
2233*4882a593Smuzhiyun goto done;
2234*4882a593Smuzhiyun }
2235*4882a593Smuzhiyun len = sprintf(buf, "%s rssi %d\n", bss_info.ssid.ssid,
2236*4882a593Smuzhiyun signal.bcn_rssi_avg) +
2237*4882a593Smuzhiyun 1;
2238*4882a593Smuzhiyun } else {
2239*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2240*4882a593Smuzhiyun }
2241*4882a593Smuzhiyun } else if (strncmp(buf, "LINKSPEED", strlen("LINKSPEED")) == 0) {
2242*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2243*4882a593Smuzhiyun woal_set_get_data_rate(priv, MLAN_ACT_GET, &rate)) {
2244*4882a593Smuzhiyun ret = -EFAULT;
2245*4882a593Smuzhiyun goto done;
2246*4882a593Smuzhiyun }
2247*4882a593Smuzhiyun PRINTM(MIOCTL, "tx rate=%d\n", (int)rate.rate);
2248*4882a593Smuzhiyun len = sprintf(buf, "LinkSpeed %d\n",
2249*4882a593Smuzhiyun (int)(rate.rate * 500000 / 1000000)) +
2250*4882a593Smuzhiyun 1;
2251*4882a593Smuzhiyun } else if (strncmp(buf, "MACADDR", strlen("MACADDR")) == 0) {
2252*4882a593Smuzhiyun len = sprintf(buf, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
2253*4882a593Smuzhiyun priv->current_addr[0], priv->current_addr[1],
2254*4882a593Smuzhiyun priv->current_addr[2], priv->current_addr[3],
2255*4882a593Smuzhiyun priv->current_addr[4], priv->current_addr[5]) +
2256*4882a593Smuzhiyun 1;
2257*4882a593Smuzhiyun } else if (strncmp(buf, "GETPOWER", strlen("GETPOWER")) == 0) {
2258*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2259*4882a593Smuzhiyun woal_get_powermode(priv, &power_mode)) {
2260*4882a593Smuzhiyun ret = -EFAULT;
2261*4882a593Smuzhiyun goto done;
2262*4882a593Smuzhiyun }
2263*4882a593Smuzhiyun len = sprintf(buf, "powermode = %d\n", power_mode) + 1;
2264*4882a593Smuzhiyun } else if (strncmp(buf, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
2265*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2266*4882a593Smuzhiyun woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE)) {
2267*4882a593Smuzhiyun ret = -EFAULT;
2268*4882a593Smuzhiyun goto done;
2269*4882a593Smuzhiyun }
2270*4882a593Smuzhiyun priv->scan_type = MLAN_SCAN_TYPE_ACTIVE;
2271*4882a593Smuzhiyun PRINTM(MIOCTL, "Set Active Scan\n");
2272*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2273*4882a593Smuzhiyun } else if (strncmp(buf, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) {
2274*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2275*4882a593Smuzhiyun woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE)) {
2276*4882a593Smuzhiyun ret = -EFAULT;
2277*4882a593Smuzhiyun goto done;
2278*4882a593Smuzhiyun }
2279*4882a593Smuzhiyun priv->scan_type = MLAN_SCAN_TYPE_PASSIVE;
2280*4882a593Smuzhiyun PRINTM(MIOCTL, "Set Passive Scan\n");
2281*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2282*4882a593Smuzhiyun } else if (strncmp(buf, "POWERMODE", strlen("POWERMODE")) == 0) {
2283*4882a593Smuzhiyun if (dwrq->length > strlen("POWERMODE") + 1) {
2284*4882a593Smuzhiyun pdata = buf + strlen("POWERMODE") + 1;
2285*4882a593Smuzhiyun if (!moal_extflg_isset(priv->phandle, EXT_HW_TEST)) {
2286*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2287*4882a593Smuzhiyun woal_set_powermode(priv, pdata)) {
2288*4882a593Smuzhiyun ret = -EFAULT;
2289*4882a593Smuzhiyun goto done;
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun }
2292*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2293*4882a593Smuzhiyun } else {
2294*4882a593Smuzhiyun ret = -EFAULT;
2295*4882a593Smuzhiyun goto done;
2296*4882a593Smuzhiyun }
2297*4882a593Smuzhiyun } else if (strncmp(buf, "COUNTRY", strlen("COUNTRY")) == 0) {
2298*4882a593Smuzhiyun memset(country_code, 0, sizeof(country_code));
2299*4882a593Smuzhiyun if ((strlen(buf) - strlen("COUNTRY") - 1) > COUNTRY_CODE_LEN) {
2300*4882a593Smuzhiyun ret = -EFAULT;
2301*4882a593Smuzhiyun goto done;
2302*4882a593Smuzhiyun }
2303*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, country_code,
2304*4882a593Smuzhiyun buf + strlen("COUNTRY") + 1,
2305*4882a593Smuzhiyun COUNTRY_CODE_LEN - 1, sizeof(country_code) - 1);
2306*4882a593Smuzhiyun PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code);
2307*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2308*4882a593Smuzhiyun woal_set_region_code(priv, country_code)) {
2309*4882a593Smuzhiyun ret = -EFAULT;
2310*4882a593Smuzhiyun goto done;
2311*4882a593Smuzhiyun }
2312*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2313*4882a593Smuzhiyun } else if (memcmp(buf, WEXT_CSCAN_HEADER, strlen(WEXT_CSCAN_HEADER)) ==
2314*4882a593Smuzhiyun 0) {
2315*4882a593Smuzhiyun PRINTM(MIOCTL, "Set Combo Scan\n");
2316*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2317*4882a593Smuzhiyun woal_set_combo_scan(priv, buf, dwrq->length)) {
2318*4882a593Smuzhiyun ret = -EFAULT;
2319*4882a593Smuzhiyun goto done;
2320*4882a593Smuzhiyun }
2321*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2322*4882a593Smuzhiyun } else if (strncmp(buf, "GETBAND", strlen("GETBAND")) == 0) {
2323*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_get_band(priv, &band)) {
2324*4882a593Smuzhiyun ret = -EFAULT;
2325*4882a593Smuzhiyun goto done;
2326*4882a593Smuzhiyun }
2327*4882a593Smuzhiyun len = sprintf(buf, "Band %d\n", band) + 1;
2328*4882a593Smuzhiyun } else if (strncmp(buf, "SETBAND", strlen("SETBAND")) == 0) {
2329*4882a593Smuzhiyun pband = buf + strlen("SETBAND") + 1;
2330*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_set_band(priv, pband)) {
2331*4882a593Smuzhiyun ret = -EFAULT;
2332*4882a593Smuzhiyun goto done;
2333*4882a593Smuzhiyun }
2334*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2335*4882a593Smuzhiyun } else if (strncmp(buf, "START", strlen("START")) == 0) {
2336*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2337*4882a593Smuzhiyun } else if (strncmp(buf, "STOP", strlen("STOP")) == 0) {
2338*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2339*4882a593Smuzhiyun } else if (strncmp(buf, "SETSUSPENDOPT", strlen("SETSUSPENDOPT")) ==
2340*4882a593Smuzhiyun 0) {
2341*4882a593Smuzhiyun /* it will be done by GUI */
2342*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2343*4882a593Smuzhiyun } else if (strncmp(buf, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
2344*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2345*4882a593Smuzhiyun } else if (strncmp(buf, "BTCOEXSCAN-START",
2346*4882a593Smuzhiyun strlen("BTCOEXSCAN-START")) == 0) {
2347*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2348*4882a593Smuzhiyun } else if (strncmp(buf, "BTCOEXSCAN-STOP", strlen("BTCOEXSCAN-STOP")) ==
2349*4882a593Smuzhiyun 0) {
2350*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2351*4882a593Smuzhiyun } else if (strncmp(buf, "BGSCAN-START", strlen("BGSCAN-START")) == 0) {
2352*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2353*4882a593Smuzhiyun } else if (strncmp(buf, "BGSCAN-CONFIG", strlen("BGSCAN-CONFIG")) ==
2354*4882a593Smuzhiyun 0) {
2355*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2356*4882a593Smuzhiyun woal_set_bg_scan(priv, buf, dwrq->length)) {
2357*4882a593Smuzhiyun ret = -EFAULT;
2358*4882a593Smuzhiyun goto done;
2359*4882a593Smuzhiyun }
2360*4882a593Smuzhiyun priv->bg_scan_start = MTRUE;
2361*4882a593Smuzhiyun priv->bg_scan_reported = MFALSE;
2362*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2363*4882a593Smuzhiyun } else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) {
2364*4882a593Smuzhiyun if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) {
2365*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2366*4882a593Smuzhiyun woal_stop_bg_scan(priv, MOAL_IOCTL_WAIT)) {
2367*4882a593Smuzhiyun ret = -EFAULT;
2368*4882a593Smuzhiyun goto done;
2369*4882a593Smuzhiyun }
2370*4882a593Smuzhiyun priv->bg_scan_start = MFALSE;
2371*4882a593Smuzhiyun priv->bg_scan_reported = MFALSE;
2372*4882a593Smuzhiyun }
2373*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2374*4882a593Smuzhiyun } else if (strncmp(buf, "RXFILTER-START", strlen("RXFILTER-START")) ==
2375*4882a593Smuzhiyun 0) {
2376*4882a593Smuzhiyun #ifdef MEF_CFG_RX_FILTER
2377*4882a593Smuzhiyun ret = woal_set_rxfilter(priv, MTRUE);
2378*4882a593Smuzhiyun if (ret)
2379*4882a593Smuzhiyun goto done;
2380*4882a593Smuzhiyun #endif
2381*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2382*4882a593Smuzhiyun } else if (strncmp(buf, "RXFILTER-STOP", strlen("RXFILTER-STOP")) ==
2383*4882a593Smuzhiyun 0) {
2384*4882a593Smuzhiyun #ifdef MEF_CFG_RX_FILTER
2385*4882a593Smuzhiyun ret = woal_set_rxfilter(priv, MFALSE);
2386*4882a593Smuzhiyun if (ret)
2387*4882a593Smuzhiyun goto done;
2388*4882a593Smuzhiyun #endif
2389*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2390*4882a593Smuzhiyun } else if (strncmp(buf, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) {
2391*4882a593Smuzhiyun if (dwrq->length > strlen("RXFILTER-ADD") + 1) {
2392*4882a593Smuzhiyun pdata = buf + strlen("RXFILTER-ADD") + 1;
2393*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2394*4882a593Smuzhiyun woal_add_rxfilter(priv, pdata)) {
2395*4882a593Smuzhiyun ret = -EFAULT;
2396*4882a593Smuzhiyun goto done;
2397*4882a593Smuzhiyun }
2398*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2399*4882a593Smuzhiyun } else {
2400*4882a593Smuzhiyun ret = -EFAULT;
2401*4882a593Smuzhiyun goto done;
2402*4882a593Smuzhiyun }
2403*4882a593Smuzhiyun } else if (strncmp(buf, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) ==
2404*4882a593Smuzhiyun 0) {
2405*4882a593Smuzhiyun if (dwrq->length > strlen("RXFILTER-REMOVE") + 1) {
2406*4882a593Smuzhiyun pdata = buf + strlen("RXFILTER-REMOVE") + 1;
2407*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2408*4882a593Smuzhiyun woal_remove_rxfilter(priv, pdata)) {
2409*4882a593Smuzhiyun ret = -EFAULT;
2410*4882a593Smuzhiyun goto done;
2411*4882a593Smuzhiyun }
2412*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2413*4882a593Smuzhiyun } else {
2414*4882a593Smuzhiyun ret = -EFAULT;
2415*4882a593Smuzhiyun goto done;
2416*4882a593Smuzhiyun }
2417*4882a593Smuzhiyun } else if (strncmp(buf, "QOSINFO", strlen("QOSINFO")) == 0) {
2418*4882a593Smuzhiyun if (dwrq->length > strlen("QOSINFO") + 1) {
2419*4882a593Smuzhiyun pdata = buf + strlen("QOSINFO") + 1;
2420*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2421*4882a593Smuzhiyun woal_priv_qos_cfg(priv, MLAN_ACT_SET, pdata)) {
2422*4882a593Smuzhiyun ret = -EFAULT;
2423*4882a593Smuzhiyun goto done;
2424*4882a593Smuzhiyun }
2425*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2426*4882a593Smuzhiyun } else {
2427*4882a593Smuzhiyun ret = -EFAULT;
2428*4882a593Smuzhiyun goto done;
2429*4882a593Smuzhiyun }
2430*4882a593Smuzhiyun } else if (strncmp(buf, "SLEEPPD", strlen("SLEEPPD")) == 0) {
2431*4882a593Smuzhiyun if (dwrq->length > strlen("SLEEPPD") + 1) {
2432*4882a593Smuzhiyun pdata = buf + strlen("SLEEPPD") + 1;
2433*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2434*4882a593Smuzhiyun woal_set_sleeppd(priv, pdata)) {
2435*4882a593Smuzhiyun ret = -EFAULT;
2436*4882a593Smuzhiyun goto done;
2437*4882a593Smuzhiyun }
2438*4882a593Smuzhiyun len = sprintf(buf, "OK\n") + 1;
2439*4882a593Smuzhiyun } else {
2440*4882a593Smuzhiyun ret = -EFAULT;
2441*4882a593Smuzhiyun goto done;
2442*4882a593Smuzhiyun }
2443*4882a593Smuzhiyun } else {
2444*4882a593Smuzhiyun PRINTM(MIOCTL, "Unknow PRIVATE command: %s, ignored\n", buf);
2445*4882a593Smuzhiyun ret = -EFAULT;
2446*4882a593Smuzhiyun goto done;
2447*4882a593Smuzhiyun }
2448*4882a593Smuzhiyun PRINTM(MIOCTL, "PRIV Command return: %s, length=%d\n", buf, len);
2449*4882a593Smuzhiyun dwrq->length = (t_u16)len;
2450*4882a593Smuzhiyun if (copy_to_user((void __user *)dwrq->pointer, buf, dwrq->length))
2451*4882a593Smuzhiyun ret = -EFAULT;
2452*4882a593Smuzhiyun done:
2453*4882a593Smuzhiyun kfree(buf);
2454*4882a593Smuzhiyun LEAVE();
2455*4882a593Smuzhiyun return ret;
2456*4882a593Smuzhiyun }
2457*4882a593Smuzhiyun
2458*4882a593Smuzhiyun /**
2459*4882a593Smuzhiyun * @brief Request a scan
2460*4882a593Smuzhiyun *
2461*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
2462*4882a593Smuzhiyun * @param wait_option Wait option
2463*4882a593Smuzhiyun * @param req_ssid A pointer to mlan_802_11_ssid structure
2464*4882a593Smuzhiyun *
2465*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS -- success, otherwise fail
2466*4882a593Smuzhiyun */
woal_wext_request_scan(moal_private * priv,t_u8 wait_option,mlan_802_11_ssid * req_ssid)2467*4882a593Smuzhiyun static mlan_status woal_wext_request_scan(moal_private *priv, t_u8 wait_option,
2468*4882a593Smuzhiyun mlan_802_11_ssid *req_ssid)
2469*4882a593Smuzhiyun {
2470*4882a593Smuzhiyun wlan_user_scan_cfg *scan_req;
2471*4882a593Smuzhiyun mlan_scan_cfg scan_cfg;
2472*4882a593Smuzhiyun mlan_status status;
2473*4882a593Smuzhiyun ENTER();
2474*4882a593Smuzhiyun if (!woal_is_any_interface_active(priv->phandle)) {
2475*4882a593Smuzhiyun LEAVE();
2476*4882a593Smuzhiyun return woal_request_scan(priv, wait_option, req_ssid);
2477*4882a593Smuzhiyun }
2478*4882a593Smuzhiyun scan_req = (wlan_user_scan_cfg *)kmalloc(sizeof(wlan_user_scan_cfg),
2479*4882a593Smuzhiyun GFP_KERNEL);
2480*4882a593Smuzhiyun if (!scan_req) {
2481*4882a593Smuzhiyun PRINTM(MERROR, "Malloc buffer failed\n");
2482*4882a593Smuzhiyun LEAVE();
2483*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
2484*4882a593Smuzhiyun }
2485*4882a593Smuzhiyun
2486*4882a593Smuzhiyun memset(&scan_cfg, 0, sizeof(scan_cfg));
2487*4882a593Smuzhiyun memset(scan_req, 0, sizeof(wlan_user_scan_cfg));
2488*4882a593Smuzhiyun if (req_ssid && req_ssid->ssid_len != 0) {
2489*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, scan_req->ssid_list[0].ssid,
2490*4882a593Smuzhiyun req_ssid->ssid, req_ssid->ssid_len,
2491*4882a593Smuzhiyun MLAN_MAX_SSID_LENGTH);
2492*4882a593Smuzhiyun scan_req->ssid_list[0].max_len = 0;
2493*4882a593Smuzhiyun }
2494*4882a593Smuzhiyun woal_get_scan_config(priv, &scan_cfg);
2495*4882a593Smuzhiyun if (scan_cfg.scan_chan_gap)
2496*4882a593Smuzhiyun scan_req->scan_chan_gap = scan_cfg.scan_chan_gap;
2497*4882a593Smuzhiyun else
2498*4882a593Smuzhiyun scan_req->scan_chan_gap = priv->phandle->scan_chan_gap;
2499*4882a593Smuzhiyun /** indicate FW, gap is optional */
2500*4882a593Smuzhiyun if (scan_req->scan_chan_gap && priv->phandle->pref_mac)
2501*4882a593Smuzhiyun scan_req->scan_chan_gap |= GAP_FLAG_OPTIONAL;
2502*4882a593Smuzhiyun status = woal_request_userscan(priv, wait_option, scan_req);
2503*4882a593Smuzhiyun kfree(scan_req);
2504*4882a593Smuzhiyun LEAVE();
2505*4882a593Smuzhiyun return status;
2506*4882a593Smuzhiyun }
2507*4882a593Smuzhiyun
2508*4882a593Smuzhiyun /**
2509*4882a593Smuzhiyun * @brief Scan Network
2510*4882a593Smuzhiyun *
2511*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2512*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
2513*4882a593Smuzhiyun * @param vwrq A pointer to iw_param structure
2514*4882a593Smuzhiyun * @param extra A pointer to extra data buf
2515*4882a593Smuzhiyun *
2516*4882a593Smuzhiyun * @return 0--success, otherwise fail
2517*4882a593Smuzhiyun */
woal_set_scan(struct net_device * dev,struct iw_request_info * info,struct iw_param * vwrq,char * extra)2518*4882a593Smuzhiyun static int woal_set_scan(struct net_device *dev, struct iw_request_info *info,
2519*4882a593Smuzhiyun struct iw_param *vwrq, char *extra)
2520*4882a593Smuzhiyun {
2521*4882a593Smuzhiyun int ret = 0;
2522*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2523*4882a593Smuzhiyun moal_handle *handle = priv->phandle;
2524*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
2525*4882a593Smuzhiyun struct iw_scan_req *req;
2526*4882a593Smuzhiyun struct iw_point *dwrq = (struct iw_point *)vwrq;
2527*4882a593Smuzhiyun #endif
2528*4882a593Smuzhiyun mlan_802_11_ssid req_ssid;
2529*4882a593Smuzhiyun
2530*4882a593Smuzhiyun ENTER();
2531*4882a593Smuzhiyun if (handle->scan_pending_on_block == MTRUE) {
2532*4882a593Smuzhiyun PRINTM(MINFO, "scan already in processing...\n");
2533*4882a593Smuzhiyun LEAVE();
2534*4882a593Smuzhiyun return ret;
2535*4882a593Smuzhiyun }
2536*4882a593Smuzhiyun #ifdef REASSOCIATION
2537*4882a593Smuzhiyun if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
2538*4882a593Smuzhiyun PRINTM(MERROR, "Acquire semaphore error, woal_set_scan\n");
2539*4882a593Smuzhiyun LEAVE();
2540*4882a593Smuzhiyun return -EBUSY;
2541*4882a593Smuzhiyun }
2542*4882a593Smuzhiyun #endif /* REASSOCIATION */
2543*4882a593Smuzhiyun priv->report_scan_result = MTRUE;
2544*4882a593Smuzhiyun
2545*4882a593Smuzhiyun memset(&req_ssid, 0x00, sizeof(mlan_802_11_ssid));
2546*4882a593Smuzhiyun
2547*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
2548*4882a593Smuzhiyun if ((dwrq->flags & IW_SCAN_THIS_ESSID) &&
2549*4882a593Smuzhiyun (dwrq->length == sizeof(struct iw_scan_req))) {
2550*4882a593Smuzhiyun req = (struct iw_scan_req *)extra;
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun if (req->essid_len <= MLAN_MAX_SSID_LENGTH) {
2553*4882a593Smuzhiyun req_ssid.ssid_len = req->essid_len;
2554*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, req_ssid.ssid,
2555*4882a593Smuzhiyun (t_u8 *)req->essid, req->essid_len,
2556*4882a593Smuzhiyun sizeof(req_ssid.ssid));
2557*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2558*4882a593Smuzhiyun woal_wext_request_scan(priv, MOAL_NO_WAIT,
2559*4882a593Smuzhiyun &req_ssid)) {
2560*4882a593Smuzhiyun ret = -EFAULT;
2561*4882a593Smuzhiyun goto done;
2562*4882a593Smuzhiyun }
2563*4882a593Smuzhiyun }
2564*4882a593Smuzhiyun } else {
2565*4882a593Smuzhiyun #endif
2566*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2567*4882a593Smuzhiyun woal_wext_request_scan(priv, MOAL_NO_WAIT, &req_ssid)) {
2568*4882a593Smuzhiyun ret = -EFAULT;
2569*4882a593Smuzhiyun goto done;
2570*4882a593Smuzhiyun }
2571*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
2572*4882a593Smuzhiyun }
2573*4882a593Smuzhiyun #endif
2574*4882a593Smuzhiyun
2575*4882a593Smuzhiyun if (priv->phandle->surprise_removed) {
2576*4882a593Smuzhiyun ret = -EFAULT;
2577*4882a593Smuzhiyun goto done;
2578*4882a593Smuzhiyun }
2579*4882a593Smuzhiyun
2580*4882a593Smuzhiyun done:
2581*4882a593Smuzhiyun #ifdef REASSOCIATION
2582*4882a593Smuzhiyun MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
2583*4882a593Smuzhiyun #endif
2584*4882a593Smuzhiyun
2585*4882a593Smuzhiyun LEAVE();
2586*4882a593Smuzhiyun return ret;
2587*4882a593Smuzhiyun }
2588*4882a593Smuzhiyun
2589*4882a593Smuzhiyun /**
2590*4882a593Smuzhiyun * @brief Set essid
2591*4882a593Smuzhiyun *
2592*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2593*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
2594*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
2595*4882a593Smuzhiyun * @param extra A pointer to extra data buf
2596*4882a593Smuzhiyun *
2597*4882a593Smuzhiyun * @return 0--success, otherwise fail
2598*4882a593Smuzhiyun */
woal_set_essid(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)2599*4882a593Smuzhiyun static int woal_set_essid(struct net_device *dev, struct iw_request_info *info,
2600*4882a593Smuzhiyun union iwreq_data *wrqu, char *extra)
2601*4882a593Smuzhiyun {
2602*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2603*4882a593Smuzhiyun struct iw_point *dwrq = &wrqu->data;
2604*4882a593Smuzhiyun mlan_802_11_ssid req_ssid;
2605*4882a593Smuzhiyun mlan_ssid_bssid ssid_bssid;
2606*4882a593Smuzhiyun #ifdef REASSOCIATION
2607*4882a593Smuzhiyun moal_handle *handle = priv->phandle;
2608*4882a593Smuzhiyun mlan_bss_info bss_info;
2609*4882a593Smuzhiyun #endif
2610*4882a593Smuzhiyun int ret = 0;
2611*4882a593Smuzhiyun t_u32 mode = 0;
2612*4882a593Smuzhiyun
2613*4882a593Smuzhiyun ENTER();
2614*4882a593Smuzhiyun
2615*4882a593Smuzhiyun #ifdef REASSOCIATION
2616*4882a593Smuzhiyun /* Cancel re-association */
2617*4882a593Smuzhiyun priv->reassoc_required = MFALSE;
2618*4882a593Smuzhiyun
2619*4882a593Smuzhiyun if (MOAL_ACQ_SEMAPHORE_BLOCK(&handle->reassoc_sem)) {
2620*4882a593Smuzhiyun PRINTM(MERROR, "Acquire semaphore error, woal_set_essid\n");
2621*4882a593Smuzhiyun LEAVE();
2622*4882a593Smuzhiyun return -EBUSY;
2623*4882a593Smuzhiyun }
2624*4882a593Smuzhiyun #endif /* REASSOCIATION */
2625*4882a593Smuzhiyun
2626*4882a593Smuzhiyun /* Check the size of the string */
2627*4882a593Smuzhiyun if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
2628*4882a593Smuzhiyun ret = -E2BIG;
2629*4882a593Smuzhiyun goto setessid_ret;
2630*4882a593Smuzhiyun }
2631*4882a593Smuzhiyun if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
2632*4882a593Smuzhiyun woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE);
2633*4882a593Smuzhiyun memset(&req_ssid, 0, sizeof(mlan_802_11_ssid));
2634*4882a593Smuzhiyun memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid));
2635*4882a593Smuzhiyun
2636*4882a593Smuzhiyun #if WIRELESS_EXT > 20
2637*4882a593Smuzhiyun req_ssid.ssid_len = dwrq->length;
2638*4882a593Smuzhiyun #else
2639*4882a593Smuzhiyun req_ssid.ssid_len = dwrq->length - 1;
2640*4882a593Smuzhiyun #endif
2641*4882a593Smuzhiyun
2642*4882a593Smuzhiyun /*
2643*4882a593Smuzhiyun * Check if we asked for `any' or 'particular'
2644*4882a593Smuzhiyun */
2645*4882a593Smuzhiyun if (!dwrq->flags) {
2646*4882a593Smuzhiyun #ifdef REASSOCIATION
2647*4882a593Smuzhiyun if (!req_ssid.ssid_len) {
2648*4882a593Smuzhiyun memset(&priv->prev_ssid_bssid.ssid, 0x00,
2649*4882a593Smuzhiyun sizeof(mlan_802_11_ssid));
2650*4882a593Smuzhiyun memset(&priv->prev_ssid_bssid.bssid, 0x00,
2651*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH);
2652*4882a593Smuzhiyun goto setessid_ret;
2653*4882a593Smuzhiyun }
2654*4882a593Smuzhiyun #endif
2655*4882a593Smuzhiyun /* Do normal SSID scanning */
2656*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2657*4882a593Smuzhiyun woal_request_scan(priv, MOAL_IOCTL_WAIT, NULL)) {
2658*4882a593Smuzhiyun ret = -EFAULT;
2659*4882a593Smuzhiyun goto setessid_ret;
2660*4882a593Smuzhiyun }
2661*4882a593Smuzhiyun } else {
2662*4882a593Smuzhiyun /* Set the SSID */
2663*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, req_ssid.ssid, extra,
2664*4882a593Smuzhiyun MIN(req_ssid.ssid_len, MLAN_MAX_SSID_LENGTH),
2665*4882a593Smuzhiyun sizeof(req_ssid.ssid));
2666*4882a593Smuzhiyun if (!req_ssid.ssid_len ||
2667*4882a593Smuzhiyun (MFALSE == woal_ssid_valid(&req_ssid))) {
2668*4882a593Smuzhiyun PRINTM(MERROR, "Invalid SSID - aborting set_essid\n");
2669*4882a593Smuzhiyun ret = -EINVAL;
2670*4882a593Smuzhiyun goto setessid_ret;
2671*4882a593Smuzhiyun }
2672*4882a593Smuzhiyun
2673*4882a593Smuzhiyun PRINTM(MINFO, "Requested new SSID = %s\n",
2674*4882a593Smuzhiyun (char *)req_ssid.ssid);
2675*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &ssid_bssid.ssid, &req_ssid,
2676*4882a593Smuzhiyun sizeof(mlan_802_11_ssid),
2677*4882a593Smuzhiyun sizeof(ssid_bssid.ssid));
2678*4882a593Smuzhiyun if (MTRUE == woal_is_connected(priv, &ssid_bssid)) {
2679*4882a593Smuzhiyun PRINTM(MIOCTL, "Already connect to the network\n");
2680*4882a593Smuzhiyun goto setessid_ret;
2681*4882a593Smuzhiyun }
2682*4882a593Smuzhiyun
2683*4882a593Smuzhiyun priv->auto_assoc_priv.drv_assoc.status = MFALSE;
2684*4882a593Smuzhiyun priv->auto_assoc_priv.drv_reconnect.status = MFALSE;
2685*4882a593Smuzhiyun #ifdef REASSOCIATION
2686*4882a593Smuzhiyun if (priv->reassoc_on == MTRUE) {
2687*4882a593Smuzhiyun if (priv->auto_assoc_priv.auto_assoc_type_on &
2688*4882a593Smuzhiyun (0x1 << (AUTO_ASSOC_TYPE_DRV_ASSOC - 1))) {
2689*4882a593Smuzhiyun if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
2690*4882a593Smuzhiyun woal_set_scan_type(
2691*4882a593Smuzhiyun priv, MLAN_SCAN_TYPE_PASSIVE);
2692*4882a593Smuzhiyun MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
2693*4882a593Smuzhiyun moal_memcpy_ext(
2694*4882a593Smuzhiyun priv->phandle,
2695*4882a593Smuzhiyun &priv->prev_ssid_bssid.ssid, &req_ssid,
2696*4882a593Smuzhiyun sizeof(mlan_802_11_ssid),
2697*4882a593Smuzhiyun sizeof(priv->prev_ssid_bssid.ssid));
2698*4882a593Smuzhiyun priv->auto_assoc_priv.auto_assoc_trigger_flag =
2699*4882a593Smuzhiyun AUTO_ASSOC_TYPE_DRV_ASSOC;
2700*4882a593Smuzhiyun priv->auto_assoc_priv.drv_assoc.status = MTRUE;
2701*4882a593Smuzhiyun priv->reassoc_required = MTRUE;
2702*4882a593Smuzhiyun priv->phandle->is_reassoc_timer_set = MTRUE;
2703*4882a593Smuzhiyun PRINTM(MINFO,
2704*4882a593Smuzhiyun " auto assoc: trigger driver auto assoc\n");
2705*4882a593Smuzhiyun woal_mod_timer(&priv->phandle->reassoc_timer,
2706*4882a593Smuzhiyun 0);
2707*4882a593Smuzhiyun ret = MLAN_STATUS_SUCCESS;
2708*4882a593Smuzhiyun
2709*4882a593Smuzhiyun LEAVE();
2710*4882a593Smuzhiyun return ret;
2711*4882a593Smuzhiyun }
2712*4882a593Smuzhiyun }
2713*4882a593Smuzhiyun #endif
2714*4882a593Smuzhiyun
2715*4882a593Smuzhiyun if (dwrq->flags != 0xFFFF) {
2716*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2717*4882a593Smuzhiyun woal_find_essid(priv, &ssid_bssid,
2718*4882a593Smuzhiyun MOAL_IOCTL_WAIT)) {
2719*4882a593Smuzhiyun /* Do specific SSID scanning */
2720*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2721*4882a593Smuzhiyun woal_request_scan(priv, MOAL_IOCTL_WAIT,
2722*4882a593Smuzhiyun &req_ssid)) {
2723*4882a593Smuzhiyun ret = -EFAULT;
2724*4882a593Smuzhiyun goto setessid_ret;
2725*4882a593Smuzhiyun }
2726*4882a593Smuzhiyun }
2727*4882a593Smuzhiyun }
2728*4882a593Smuzhiyun }
2729*4882a593Smuzhiyun
2730*4882a593Smuzhiyun mode = woal_get_mode(priv, MOAL_IOCTL_WAIT);
2731*4882a593Smuzhiyun if (mode == IW_MODE_ADHOC)
2732*4882a593Smuzhiyun /* disconnect before try to associate */
2733*4882a593Smuzhiyun woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL,
2734*4882a593Smuzhiyun DEF_DEAUTH_REASON_CODE);
2735*4882a593Smuzhiyun
2736*4882a593Smuzhiyun if (mode != IW_MODE_ADHOC) {
2737*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2738*4882a593Smuzhiyun woal_find_best_network(priv, MOAL_IOCTL_WAIT,
2739*4882a593Smuzhiyun &ssid_bssid)) {
2740*4882a593Smuzhiyun ret = -EFAULT;
2741*4882a593Smuzhiyun goto setessid_ret;
2742*4882a593Smuzhiyun }
2743*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2744*4882a593Smuzhiyun woal_11d_check_ap_channel(priv, MOAL_IOCTL_WAIT,
2745*4882a593Smuzhiyun &ssid_bssid)) {
2746*4882a593Smuzhiyun PRINTM(MERROR,
2747*4882a593Smuzhiyun "The AP's channel is invalid for current region\n");
2748*4882a593Smuzhiyun ret = -EFAULT;
2749*4882a593Smuzhiyun goto setessid_ret;
2750*4882a593Smuzhiyun }
2751*4882a593Smuzhiyun } else if (MLAN_STATUS_SUCCESS !=
2752*4882a593Smuzhiyun woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid))
2753*4882a593Smuzhiyun /* Adhoc start, Check the channel command */
2754*4882a593Smuzhiyun woal_11h_channel_check_ioctl(priv, MOAL_IOCTL_WAIT);
2755*4882a593Smuzhiyun
2756*4882a593Smuzhiyun #ifdef REASSOCIATION
2757*4882a593Smuzhiyun if (priv->reassoc_on == MTRUE && req_ssid.ssid_len) {
2758*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
2759*4882a593Smuzhiyun &req_ssid, sizeof(mlan_802_11_ssid),
2760*4882a593Smuzhiyun sizeof(priv->prev_ssid_bssid.ssid));
2761*4882a593Smuzhiyun memset(&priv->prev_ssid_bssid.bssid, 0x00,
2762*4882a593Smuzhiyun MLAN_MAC_ADDR_LENGTH);
2763*4882a593Smuzhiyun }
2764*4882a593Smuzhiyun #endif /* REASSOCIATION */
2765*4882a593Smuzhiyun
2766*4882a593Smuzhiyun /* Connect to BSS by ESSID */
2767*4882a593Smuzhiyun memset(&ssid_bssid.bssid, 0, MLAN_MAC_ADDR_LENGTH);
2768*4882a593Smuzhiyun
2769*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2770*4882a593Smuzhiyun woal_bss_start(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) {
2771*4882a593Smuzhiyun ret = -EFAULT;
2772*4882a593Smuzhiyun goto setessid_ret;
2773*4882a593Smuzhiyun }
2774*4882a593Smuzhiyun
2775*4882a593Smuzhiyun #ifdef REASSOCIATION
2776*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
2777*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2778*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
2779*4882a593Smuzhiyun ret = -EFAULT;
2780*4882a593Smuzhiyun goto setessid_ret;
2781*4882a593Smuzhiyun }
2782*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.ssid,
2783*4882a593Smuzhiyun &bss_info.ssid, sizeof(mlan_802_11_ssid),
2784*4882a593Smuzhiyun sizeof(priv->prev_ssid_bssid.ssid));
2785*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, &priv->prev_ssid_bssid.bssid,
2786*4882a593Smuzhiyun &bss_info.bssid, MLAN_MAC_ADDR_LENGTH,
2787*4882a593Smuzhiyun sizeof(priv->prev_ssid_bssid.bssid));
2788*4882a593Smuzhiyun #endif /* REASSOCIATION */
2789*4882a593Smuzhiyun
2790*4882a593Smuzhiyun setessid_ret:
2791*4882a593Smuzhiyun if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE)
2792*4882a593Smuzhiyun woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE);
2793*4882a593Smuzhiyun #ifdef REASSOCIATION
2794*4882a593Smuzhiyun MOAL_REL_SEMAPHORE(&handle->reassoc_sem);
2795*4882a593Smuzhiyun #endif
2796*4882a593Smuzhiyun LEAVE();
2797*4882a593Smuzhiyun return ret;
2798*4882a593Smuzhiyun }
2799*4882a593Smuzhiyun
2800*4882a593Smuzhiyun /**
2801*4882a593Smuzhiyun * @brief Get current essid
2802*4882a593Smuzhiyun *
2803*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2804*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
2805*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
2806*4882a593Smuzhiyun * @param extra A pointer to extra data buf
2807*4882a593Smuzhiyun *
2808*4882a593Smuzhiyun * @return 0--success, otherwise fail
2809*4882a593Smuzhiyun */
woal_get_essid(struct net_device * dev,struct iw_request_info * info,struct iw_point * dwrq,char * extra)2810*4882a593Smuzhiyun static int woal_get_essid(struct net_device *dev, struct iw_request_info *info,
2811*4882a593Smuzhiyun struct iw_point *dwrq, char *extra)
2812*4882a593Smuzhiyun {
2813*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2814*4882a593Smuzhiyun mlan_bss_info bss_info;
2815*4882a593Smuzhiyun int ret = 0;
2816*4882a593Smuzhiyun
2817*4882a593Smuzhiyun ENTER();
2818*4882a593Smuzhiyun
2819*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
2820*4882a593Smuzhiyun
2821*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2822*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
2823*4882a593Smuzhiyun ret = -EFAULT;
2824*4882a593Smuzhiyun goto done;
2825*4882a593Smuzhiyun }
2826*4882a593Smuzhiyun
2827*4882a593Smuzhiyun if (bss_info.media_connected) {
2828*4882a593Smuzhiyun dwrq->length = MIN(dwrq->length, bss_info.ssid.ssid_len);
2829*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, extra, bss_info.ssid.ssid,
2830*4882a593Smuzhiyun dwrq->length, dwrq->length);
2831*4882a593Smuzhiyun } else
2832*4882a593Smuzhiyun dwrq->length = 0;
2833*4882a593Smuzhiyun
2834*4882a593Smuzhiyun if (bss_info.scan_table_idx)
2835*4882a593Smuzhiyun dwrq->flags = (bss_info.scan_table_idx + 1) & IW_ENCODE_INDEX;
2836*4882a593Smuzhiyun else
2837*4882a593Smuzhiyun dwrq->flags = 1;
2838*4882a593Smuzhiyun
2839*4882a593Smuzhiyun done:
2840*4882a593Smuzhiyun LEAVE();
2841*4882a593Smuzhiyun return ret;
2842*4882a593Smuzhiyun }
2843*4882a593Smuzhiyun
2844*4882a593Smuzhiyun /**
2845*4882a593Smuzhiyun * @brief Retrieve the scan table entries via wireless tools IOCTL call
2846*4882a593Smuzhiyun *
2847*4882a593Smuzhiyun * @param dev A pointer to net_device structure
2848*4882a593Smuzhiyun * @param info A pointer to iw_request_info structure
2849*4882a593Smuzhiyun * @param dwrq A pointer to iw_point structure
2850*4882a593Smuzhiyun * @param extra A pointer to extra data buf
2851*4882a593Smuzhiyun *
2852*4882a593Smuzhiyun * @return 0--success, otherwise fail
2853*4882a593Smuzhiyun */
woal_get_scan(struct net_device * dev,struct iw_request_info * info,struct iw_point * dwrq,char * extra)2854*4882a593Smuzhiyun static int woal_get_scan(struct net_device *dev, struct iw_request_info *info,
2855*4882a593Smuzhiyun struct iw_point *dwrq, char *extra)
2856*4882a593Smuzhiyun {
2857*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
2858*4882a593Smuzhiyun int ret = 0;
2859*4882a593Smuzhiyun char *current_ev = extra;
2860*4882a593Smuzhiyun char *end_buf = extra + IW_SCAN_MAX_DATA;
2861*4882a593Smuzhiyun char *current_val; /* For rates */
2862*4882a593Smuzhiyun struct iw_event iwe; /* Temporary buffer */
2863*4882a593Smuzhiyun unsigned int i;
2864*4882a593Smuzhiyun unsigned int j;
2865*4882a593Smuzhiyun mlan_scan_resp scan_resp;
2866*4882a593Smuzhiyun mlan_bss_info bss_info;
2867*4882a593Smuzhiyun BSSDescriptor_t *scan_table;
2868*4882a593Smuzhiyun mlan_ds_get_signal rssi;
2869*4882a593Smuzhiyun t_u16 buf_size = 16 + 256 * 2;
2870*4882a593Smuzhiyun char *buf = NULL;
2871*4882a593Smuzhiyun char *ptr;
2872*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
2873*4882a593Smuzhiyun t_u8 *praw_data;
2874*4882a593Smuzhiyun #endif
2875*4882a593Smuzhiyun int beacon_size;
2876*4882a593Smuzhiyun t_u8 *pbeacon;
2877*4882a593Smuzhiyun IEEEtypes_ElementId_e element_id;
2878*4882a593Smuzhiyun t_u8 element_len;
2879*4882a593Smuzhiyun gfp_t flag;
2880*4882a593Smuzhiyun
2881*4882a593Smuzhiyun ENTER();
2882*4882a593Smuzhiyun
2883*4882a593Smuzhiyun if (priv->phandle->scan_pending_on_block == MTRUE) {
2884*4882a593Smuzhiyun LEAVE();
2885*4882a593Smuzhiyun return -EAGAIN;
2886*4882a593Smuzhiyun }
2887*4882a593Smuzhiyun flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
2888*4882a593Smuzhiyun buf = kzalloc((buf_size), flag);
2889*4882a593Smuzhiyun if (!buf) {
2890*4882a593Smuzhiyun PRINTM(MERROR, "Cannot allocate buffer!\n");
2891*4882a593Smuzhiyun ret = -EFAULT;
2892*4882a593Smuzhiyun goto done;
2893*4882a593Smuzhiyun }
2894*4882a593Smuzhiyun
2895*4882a593Smuzhiyun memset(&bss_info, 0, sizeof(bss_info));
2896*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2897*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) {
2898*4882a593Smuzhiyun ret = -EFAULT;
2899*4882a593Smuzhiyun goto done;
2900*4882a593Smuzhiyun }
2901*4882a593Smuzhiyun memset(&scan_resp, 0, sizeof(scan_resp));
2902*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
2903*4882a593Smuzhiyun woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) {
2904*4882a593Smuzhiyun ret = -EFAULT;
2905*4882a593Smuzhiyun goto done;
2906*4882a593Smuzhiyun }
2907*4882a593Smuzhiyun scan_table = (BSSDescriptor_t *)scan_resp.pscan_table;
2908*4882a593Smuzhiyun if (dwrq->length)
2909*4882a593Smuzhiyun end_buf = extra + dwrq->length;
2910*4882a593Smuzhiyun if (priv->media_connected == MTRUE)
2911*4882a593Smuzhiyun PRINTM(MINFO, "Current Ssid: %-32s\n", bss_info.ssid.ssid);
2912*4882a593Smuzhiyun PRINTM(MINFO, "Scan: Get: NumInScanTable = %d\n",
2913*4882a593Smuzhiyun (int)scan_resp.num_in_scan_table);
2914*4882a593Smuzhiyun
2915*4882a593Smuzhiyun #if WIRELESS_EXT > 13
2916*4882a593Smuzhiyun /* The old API using SIOCGIWAPLIST had a hard limit of
2917*4882a593Smuzhiyun * IW_MAX_AP. The new API using SIOCGIWSCAN is only
2918*4882a593Smuzhiyun * limited by buffer size WE-14 -> WE-16 the buffer is
2919*4882a593Smuzhiyun * limited to IW_SCAN_MAX_DATA bytes which is 4096.
2920*4882a593Smuzhiyun */
2921*4882a593Smuzhiyun for (i = 0; i < MIN(scan_resp.num_in_scan_table, 64); i++) {
2922*4882a593Smuzhiyun if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) {
2923*4882a593Smuzhiyun PRINTM(MINFO,
2924*4882a593Smuzhiyun "i=%d break out: current_ev=%p end_buf=%p "
2925*4882a593Smuzhiyun "MAX_SCAN_CELL_SIZE=%d\n",
2926*4882a593Smuzhiyun i, current_ev, end_buf,
2927*4882a593Smuzhiyun (t_u32)MAX_SCAN_CELL_SIZE);
2928*4882a593Smuzhiyun ret = -E2BIG;
2929*4882a593Smuzhiyun break;
2930*4882a593Smuzhiyun }
2931*4882a593Smuzhiyun if (!scan_table[i].freq) {
2932*4882a593Smuzhiyun PRINTM(MWARN, "Invalid channel number %d\n",
2933*4882a593Smuzhiyun (int)scan_table[i].channel);
2934*4882a593Smuzhiyun continue;
2935*4882a593Smuzhiyun }
2936*4882a593Smuzhiyun PRINTM(MINFO, "i=%d Ssid: %-32s\n", i,
2937*4882a593Smuzhiyun scan_table[i].ssid.ssid);
2938*4882a593Smuzhiyun
2939*4882a593Smuzhiyun /* check ssid is valid or not, ex. hidden ssid will be filter
2940*4882a593Smuzhiyun * out */
2941*4882a593Smuzhiyun if (woal_ssid_valid(&scan_table[i].ssid) == MFALSE)
2942*4882a593Smuzhiyun continue;
2943*4882a593Smuzhiyun
2944*4882a593Smuzhiyun /* First entry *MUST* be the AP MAC address */
2945*4882a593Smuzhiyun iwe.cmd = SIOCGIWAP;
2946*4882a593Smuzhiyun iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2947*4882a593Smuzhiyun moal_memcpy_ext(priv->phandle, iwe.u.ap_addr.sa_data,
2948*4882a593Smuzhiyun &scan_table[i].mac_address, ETH_ALEN,
2949*4882a593Smuzhiyun sizeof(iwe.u.ap_addr.sa_data));
2950*4882a593Smuzhiyun
2951*4882a593Smuzhiyun iwe.len = IW_EV_ADDR_LEN;
2952*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
2953*4882a593Smuzhiyun &iwe, iwe.len);
2954*4882a593Smuzhiyun
2955*4882a593Smuzhiyun /* Add the ESSID */
2956*4882a593Smuzhiyun iwe.u.data.length = scan_table[i].ssid.ssid_len;
2957*4882a593Smuzhiyun
2958*4882a593Smuzhiyun if (iwe.u.data.length > 32)
2959*4882a593Smuzhiyun iwe.u.data.length = 32;
2960*4882a593Smuzhiyun
2961*4882a593Smuzhiyun iwe.cmd = SIOCGIWESSID;
2962*4882a593Smuzhiyun iwe.u.essid.flags = (i + 1) & IW_ENCODE_INDEX;
2963*4882a593Smuzhiyun iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
2964*4882a593Smuzhiyun current_ev =
2965*4882a593Smuzhiyun IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe,
2966*4882a593Smuzhiyun (char *)scan_table[i].ssid.ssid);
2967*4882a593Smuzhiyun
2968*4882a593Smuzhiyun /* Add mode */
2969*4882a593Smuzhiyun iwe.cmd = SIOCGIWMODE;
2970*4882a593Smuzhiyun if (scan_table[i].bss_mode == MLAN_BSS_MODE_IBSS)
2971*4882a593Smuzhiyun iwe.u.mode = IW_MODE_ADHOC;
2972*4882a593Smuzhiyun else if (scan_table[i].bss_mode == MLAN_BSS_MODE_INFRA)
2973*4882a593Smuzhiyun iwe.u.mode = IW_MODE_MASTER;
2974*4882a593Smuzhiyun else
2975*4882a593Smuzhiyun iwe.u.mode = IW_MODE_AUTO;
2976*4882a593Smuzhiyun
2977*4882a593Smuzhiyun iwe.len = IW_EV_UINT_LEN;
2978*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
2979*4882a593Smuzhiyun &iwe, iwe.len);
2980*4882a593Smuzhiyun
2981*4882a593Smuzhiyun /* Frequency */
2982*4882a593Smuzhiyun iwe.cmd = SIOCGIWFREQ;
2983*4882a593Smuzhiyun iwe.u.freq.m = (long)scan_table[i].freq;
2984*4882a593Smuzhiyun iwe.u.freq.e = 6;
2985*4882a593Smuzhiyun iwe.u.freq.flags = IW_FREQ_FIXED;
2986*4882a593Smuzhiyun iwe.len = IW_EV_FREQ_LEN;
2987*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
2988*4882a593Smuzhiyun &iwe, iwe.len);
2989*4882a593Smuzhiyun
2990*4882a593Smuzhiyun memset(&iwe, 0, sizeof(iwe));
2991*4882a593Smuzhiyun /* Add quality statistics */
2992*4882a593Smuzhiyun iwe.cmd = IWEVQUAL;
2993*4882a593Smuzhiyun iwe.u.qual.level = SCAN_RSSI(scan_table[i].rssi);
2994*4882a593Smuzhiyun if (!bss_info.bcn_nf_last)
2995*4882a593Smuzhiyun iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
2996*4882a593Smuzhiyun else
2997*4882a593Smuzhiyun iwe.u.qual.noise = bss_info.bcn_nf_last;
2998*4882a593Smuzhiyun
2999*4882a593Smuzhiyun if ((bss_info.bss_mode == MLAN_BSS_MODE_IBSS) &&
3000*4882a593Smuzhiyun !woal_ssid_cmp(&bss_info.ssid, &scan_table[i].ssid) &&
3001*4882a593Smuzhiyun bss_info.adhoc_state == ADHOC_STARTED) {
3002*4882a593Smuzhiyun memset(&rssi, 0, sizeof(mlan_ds_get_signal));
3003*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
3004*4882a593Smuzhiyun woal_get_signal_info(priv, MOAL_IOCTL_WAIT,
3005*4882a593Smuzhiyun &rssi)) {
3006*4882a593Smuzhiyun ret = -EFAULT;
3007*4882a593Smuzhiyun break;
3008*4882a593Smuzhiyun }
3009*4882a593Smuzhiyun iwe.u.qual.level = rssi.data_rssi_avg;
3010*4882a593Smuzhiyun }
3011*4882a593Smuzhiyun iwe.u.qual.qual =
3012*4882a593Smuzhiyun woal_rssi_to_quality((t_s16)(iwe.u.qual.level - 0x100));
3013*4882a593Smuzhiyun iwe.len = IW_EV_QUAL_LEN;
3014*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf,
3015*4882a593Smuzhiyun &iwe, iwe.len);
3016*4882a593Smuzhiyun
3017*4882a593Smuzhiyun /* Add encryption capability */
3018*4882a593Smuzhiyun iwe.cmd = SIOCGIWENCODE;
3019*4882a593Smuzhiyun if (scan_table[i].privacy)
3020*4882a593Smuzhiyun iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
3021*4882a593Smuzhiyun else
3022*4882a593Smuzhiyun iwe.u.data.flags = IW_ENCODE_DISABLED;
3023*4882a593Smuzhiyun
3024*4882a593Smuzhiyun iwe.u.data.length = 0;
3025*4882a593Smuzhiyun iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
3026*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,
3027*4882a593Smuzhiyun &iwe, NULL);
3028*4882a593Smuzhiyun
3029*4882a593Smuzhiyun current_val = current_ev + IW_EV_LCP_LEN;
3030*4882a593Smuzhiyun
3031*4882a593Smuzhiyun iwe.cmd = SIOCGIWRATE;
3032*4882a593Smuzhiyun
3033*4882a593Smuzhiyun iwe.u.bitrate.fixed = 0;
3034*4882a593Smuzhiyun iwe.u.bitrate.disabled = 0;
3035*4882a593Smuzhiyun iwe.u.bitrate.value = 0;
3036*4882a593Smuzhiyun
3037*4882a593Smuzhiyun /* Bit rate given in 500 kb/s units (+ 0x80) */
3038*4882a593Smuzhiyun for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
3039*4882a593Smuzhiyun if (!scan_table[i].supported_rates[j])
3040*4882a593Smuzhiyun break;
3041*4882a593Smuzhiyun
3042*4882a593Smuzhiyun iwe.u.bitrate.value =
3043*4882a593Smuzhiyun (scan_table[i].supported_rates[j] & 0x7f) *
3044*4882a593Smuzhiyun 500000;
3045*4882a593Smuzhiyun iwe.len = IW_EV_PARAM_LEN;
3046*4882a593Smuzhiyun current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
3047*4882a593Smuzhiyun current_val, end_buf,
3048*4882a593Smuzhiyun &iwe, iwe.len);
3049*4882a593Smuzhiyun }
3050*4882a593Smuzhiyun if ((bss_info.bss_mode == MLAN_BSS_MODE_IBSS) &&
3051*4882a593Smuzhiyun !woal_ssid_cmp(&bss_info.ssid, &scan_table[i].ssid) &&
3052*4882a593Smuzhiyun bss_info.adhoc_state == ADHOC_STARTED) {
3053*4882a593Smuzhiyun iwe.u.bitrate.value = 22 * 500000;
3054*4882a593Smuzhiyun iwe.len = IW_EV_PARAM_LEN;
3055*4882a593Smuzhiyun current_val = IWE_STREAM_ADD_VALUE(info, current_ev,
3056*4882a593Smuzhiyun current_val, end_buf,
3057*4882a593Smuzhiyun &iwe, iwe.len);
3058*4882a593Smuzhiyun }
3059*4882a593Smuzhiyun
3060*4882a593Smuzhiyun /* Check if an event is added */
3061*4882a593Smuzhiyun if ((unsigned int)(current_val - current_ev) >= IW_EV_PARAM_LEN)
3062*4882a593Smuzhiyun current_ev = current_val;
3063*4882a593Smuzhiyun
3064*4882a593Smuzhiyun /* Beacon Interval */
3065*4882a593Smuzhiyun memset(&iwe, 0, sizeof(iwe));
3066*4882a593Smuzhiyun ptr = buf;
3067*4882a593Smuzhiyun ptr += sprintf(ptr, "Beacon interval=%d",
3068*4882a593Smuzhiyun scan_table[i].beacon_period);
3069*4882a593Smuzhiyun
3070*4882a593Smuzhiyun iwe.u.data.length = strlen(buf);
3071*4882a593Smuzhiyun iwe.cmd = IWEVCUSTOM;
3072*4882a593Smuzhiyun iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
3073*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,
3074*4882a593Smuzhiyun &iwe, buf);
3075*4882a593Smuzhiyun current_val = current_ev + IW_EV_LCP_LEN + strlen(buf);
3076*4882a593Smuzhiyun
3077*4882a593Smuzhiyun /* Parse and send the IEs */
3078*4882a593Smuzhiyun pbeacon = scan_table[i].pbeacon_buf;
3079*4882a593Smuzhiyun beacon_size = scan_table[i].beacon_buf_size;
3080*4882a593Smuzhiyun
3081*4882a593Smuzhiyun /* Skip time stamp, beacon interval and capability */
3082*4882a593Smuzhiyun if (pbeacon) {
3083*4882a593Smuzhiyun pbeacon += sizeof(scan_table[i].beacon_period) +
3084*4882a593Smuzhiyun sizeof(scan_table[i].time_stamp) +
3085*4882a593Smuzhiyun sizeof(scan_table[i].cap_info);
3086*4882a593Smuzhiyun beacon_size -= sizeof(scan_table[i].beacon_period) +
3087*4882a593Smuzhiyun sizeof(scan_table[i].time_stamp) +
3088*4882a593Smuzhiyun sizeof(scan_table[i].cap_info);
3089*4882a593Smuzhiyun
3090*4882a593Smuzhiyun while ((unsigned int)beacon_size >=
3091*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t)) {
3092*4882a593Smuzhiyun element_id = (IEEEtypes_ElementId_e)(
3093*4882a593Smuzhiyun *(t_u8 *)pbeacon);
3094*4882a593Smuzhiyun element_len = *((t_u8 *)pbeacon + 1);
3095*4882a593Smuzhiyun if ((unsigned int)beacon_size <
3096*4882a593Smuzhiyun (unsigned int)element_len +
3097*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t)) {
3098*4882a593Smuzhiyun PRINTM(MERROR,
3099*4882a593Smuzhiyun "Get scan: Error in processing IE, "
3100*4882a593Smuzhiyun "bytes left < IE length\n");
3101*4882a593Smuzhiyun break;
3102*4882a593Smuzhiyun }
3103*4882a593Smuzhiyun
3104*4882a593Smuzhiyun switch (element_id) {
3105*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
3106*4882a593Smuzhiyun case VENDOR_SPECIFIC_221:
3107*4882a593Smuzhiyun case RSN_IE:
3108*4882a593Smuzhiyun case WAPI_IE:
3109*4882a593Smuzhiyun praw_data = (t_u8 *)pbeacon;
3110*4882a593Smuzhiyun memset(&iwe, 0, sizeof(iwe));
3111*4882a593Smuzhiyun memset(buf, 0, buf_size);
3112*4882a593Smuzhiyun ptr = buf;
3113*4882a593Smuzhiyun moal_memcpy_ext(
3114*4882a593Smuzhiyun priv->phandle, buf, praw_data,
3115*4882a593Smuzhiyun element_len +
3116*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t),
3117*4882a593Smuzhiyun buf_size);
3118*4882a593Smuzhiyun iwe.cmd = IWEVGENIE;
3119*4882a593Smuzhiyun iwe.u.data.length =
3120*4882a593Smuzhiyun element_len +
3121*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t);
3122*4882a593Smuzhiyun iwe.len = IW_EV_POINT_LEN +
3123*4882a593Smuzhiyun iwe.u.data.length;
3124*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_POINT(
3125*4882a593Smuzhiyun info, current_ev, end_buf, &iwe,
3126*4882a593Smuzhiyun buf);
3127*4882a593Smuzhiyun break;
3128*4882a593Smuzhiyun #endif
3129*4882a593Smuzhiyun default:
3130*4882a593Smuzhiyun break;
3131*4882a593Smuzhiyun }
3132*4882a593Smuzhiyun pbeacon += element_len +
3133*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t);
3134*4882a593Smuzhiyun beacon_size -= element_len +
3135*4882a593Smuzhiyun sizeof(IEEEtypes_Header_t);
3136*4882a593Smuzhiyun }
3137*4882a593Smuzhiyun }
3138*4882a593Smuzhiyun
3139*4882a593Smuzhiyun #if WIRELESS_EXT > 14
3140*4882a593Smuzhiyun memset(&iwe, 0, sizeof(iwe));
3141*4882a593Smuzhiyun memset(buf, 0, buf_size);
3142*4882a593Smuzhiyun ptr = buf;
3143*4882a593Smuzhiyun ptr += sprintf(ptr, "band=");
3144*4882a593Smuzhiyun memset(&iwe, 0, sizeof(iwe));
3145*4882a593Smuzhiyun if (scan_table[i].bss_band == BAND_A)
3146*4882a593Smuzhiyun sprintf(ptr, "a");
3147*4882a593Smuzhiyun else
3148*4882a593Smuzhiyun sprintf(ptr, "bg");
3149*4882a593Smuzhiyun iwe.u.data.length = strlen(buf);
3150*4882a593Smuzhiyun PRINTM(MINFO, "iwe.u.data.length %d\n", iwe.u.data.length);
3151*4882a593Smuzhiyun PRINTM(MINFO, "BUF: %s\n", buf);
3152*4882a593Smuzhiyun iwe.cmd = IWEVCUSTOM;
3153*4882a593Smuzhiyun iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
3154*4882a593Smuzhiyun current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,
3155*4882a593Smuzhiyun &iwe, buf);
3156*4882a593Smuzhiyun #endif
3157*4882a593Smuzhiyun current_val = current_ev + IW_EV_LCP_LEN;
3158*4882a593Smuzhiyun
3159*4882a593Smuzhiyun /*
3160*4882a593Smuzhiyun * Check if we added any event
3161*4882a593Smuzhiyun */
3162*4882a593Smuzhiyun if ((unsigned int)(current_val - current_ev) > IW_EV_LCP_LEN)
3163*4882a593Smuzhiyun current_ev = current_val;
3164*4882a593Smuzhiyun }
3165*4882a593Smuzhiyun
3166*4882a593Smuzhiyun dwrq->length = (current_ev - extra);
3167*4882a593Smuzhiyun dwrq->flags = 0;
3168*4882a593Smuzhiyun #endif
3169*4882a593Smuzhiyun
3170*4882a593Smuzhiyun done:
3171*4882a593Smuzhiyun kfree(buf);
3172*4882a593Smuzhiyun LEAVE();
3173*4882a593Smuzhiyun return ret;
3174*4882a593Smuzhiyun }
3175*4882a593Smuzhiyun
3176*4882a593Smuzhiyun /**
3177*4882a593Smuzhiyun * iwconfig settable callbacks
3178*4882a593Smuzhiyun */
3179*4882a593Smuzhiyun static const iw_handler woal_handler[] = {
3180*4882a593Smuzhiyun (iw_handler)woal_config_commit, /* SIOCSIWCOMMIT */
3181*4882a593Smuzhiyun (iw_handler)woal_get_name, /* SIOCGIWNAME */
3182*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCSIWNWID */
3183*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCGIWNWID */
3184*4882a593Smuzhiyun (iw_handler)woal_set_freq, /* SIOCSIWFREQ */
3185*4882a593Smuzhiyun (iw_handler)woal_get_freq, /* SIOCGIWFREQ */
3186*4882a593Smuzhiyun (iw_handler)woal_set_bss_mode, /* SIOCSIWMODE */
3187*4882a593Smuzhiyun (iw_handler)woal_get_bss_mode, /* SIOCGIWMODE */
3188*4882a593Smuzhiyun (iw_handler)woal_set_sens, /* SIOCSIWSENS */
3189*4882a593Smuzhiyun (iw_handler)woal_get_sens, /* SIOCGIWSENS */
3190*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCSIWRANGE */
3191*4882a593Smuzhiyun (iw_handler)woal_get_range, /* SIOCGIWRANGE */
3192*4882a593Smuzhiyun (iw_handler)woal_set_priv, /* SIOCSIWPRIV */
3193*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCGIWPRIV */
3194*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCSIWSTATS */
3195*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCGIWSTATS */
3196*4882a593Smuzhiyun #if WIRELESS_EXT > 15
3197*4882a593Smuzhiyun #ifdef CONFIG_WEXT_SPY
3198*4882a593Smuzhiyun iw_handler_set_spy, /* SIOCSIWSPY */
3199*4882a593Smuzhiyun iw_handler_get_spy, /* SIOCGIWSPY */
3200*4882a593Smuzhiyun iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
3201*4882a593Smuzhiyun iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
3202*4882a593Smuzhiyun #else
3203*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3204*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3205*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3206*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3207*4882a593Smuzhiyun #endif
3208*4882a593Smuzhiyun #else /* WIRELESS_EXT > 15 */
3209*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3210*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3211*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3212*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3213*4882a593Smuzhiyun #endif /* WIRELESS_EXT > 15 */
3214*4882a593Smuzhiyun (iw_handler)woal_set_wap, /* SIOCSIWAP */
3215*4882a593Smuzhiyun (iw_handler)woal_get_wap, /* SIOCGIWAP */
3216*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
3217*4882a593Smuzhiyun (iw_handler)woal_set_mlme, /* SIOCSIWMLME */
3218*4882a593Smuzhiyun #else
3219*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3220*4882a593Smuzhiyun #endif
3221*4882a593Smuzhiyun /* (iw_handler) wlan_get_aplist, */ /* SIOCGIWAPLIST */
3222*4882a593Smuzhiyun NULL, /* SIOCGIWAPLIST */
3223*4882a593Smuzhiyun #if WIRELESS_EXT > 13
3224*4882a593Smuzhiyun (iw_handler)woal_set_scan, /* SIOCSIWSCAN */
3225*4882a593Smuzhiyun (iw_handler)woal_get_scan, /* SIOCGIWSCAN */
3226*4882a593Smuzhiyun #else /* WIRELESS_EXT > 13 */
3227*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCSIWSCAN */
3228*4882a593Smuzhiyun (iw_handler)NULL, /* SIOCGIWSCAN */
3229*4882a593Smuzhiyun #endif /* WIRELESS_EXT > 13 */
3230*4882a593Smuzhiyun (iw_handler)woal_set_essid, /* SIOCSIWESSID */
3231*4882a593Smuzhiyun (iw_handler)woal_get_essid, /* SIOCGIWESSID */
3232*4882a593Smuzhiyun (iw_handler)woal_set_nick, /* SIOCSIWNICKN */
3233*4882a593Smuzhiyun (iw_handler)woal_get_nick, /* SIOCGIWNICKN */
3234*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3235*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3236*4882a593Smuzhiyun (iw_handler)woal_set_rate, /* SIOCSIWRATE */
3237*4882a593Smuzhiyun (iw_handler)woal_get_rate, /* SIOCGIWRATE */
3238*4882a593Smuzhiyun (iw_handler)woal_set_rts, /* SIOCSIWRTS */
3239*4882a593Smuzhiyun (iw_handler)woal_get_rts, /* SIOCGIWRTS */
3240*4882a593Smuzhiyun (iw_handler)woal_set_frag, /* SIOCSIWFRAG */
3241*4882a593Smuzhiyun (iw_handler)woal_get_frag, /* SIOCGIWFRAG */
3242*4882a593Smuzhiyun (iw_handler)woal_set_txpow, /* SIOCSIWTXPOW */
3243*4882a593Smuzhiyun (iw_handler)woal_get_txpow, /* SIOCGIWTXPOW */
3244*4882a593Smuzhiyun (iw_handler)woal_set_retry, /* SIOCSIWRETRY */
3245*4882a593Smuzhiyun (iw_handler)woal_get_retry, /* SIOCGIWRETRY */
3246*4882a593Smuzhiyun (iw_handler)woal_set_encode, /* SIOCSIWENCODE */
3247*4882a593Smuzhiyun (iw_handler)woal_get_encode, /* SIOCGIWENCODE */
3248*4882a593Smuzhiyun (iw_handler)woal_set_power, /* SIOCSIWPOWER */
3249*4882a593Smuzhiyun (iw_handler)woal_get_power, /* SIOCGIWPOWER */
3250*4882a593Smuzhiyun #if (WIRELESS_EXT >= 18)
3251*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3252*4882a593Smuzhiyun (iw_handler)NULL, /* -- hole -- */
3253*4882a593Smuzhiyun (iw_handler)woal_set_gen_ie, /* SIOCSIWGENIE */
3254*4882a593Smuzhiyun (iw_handler)woal_get_gen_ie, /* SIOCGIWGENIE */
3255*4882a593Smuzhiyun (iw_handler)woal_set_auth, /* SIOCSIWAUTH */
3256*4882a593Smuzhiyun (iw_handler)woal_get_auth, /* SIOCGIWAUTH */
3257*4882a593Smuzhiyun (iw_handler)woal_set_encode_ext, /* SIOCSIWENCODEEXT */
3258*4882a593Smuzhiyun (iw_handler)woal_get_encode_ext, /* SIOCGIWENCODEEXT */
3259*4882a593Smuzhiyun (iw_handler)woal_set_pmksa, /* SIOCSIWPMKSA */
3260*4882a593Smuzhiyun #endif /* WIRELESSS_EXT >= 18 */
3261*4882a593Smuzhiyun };
3262*4882a593Smuzhiyun
3263*4882a593Smuzhiyun /**
3264*4882a593Smuzhiyun * iwpriv settable callbacks
3265*4882a593Smuzhiyun */
3266*4882a593Smuzhiyun static const iw_handler woal_private_handler[] = {
3267*4882a593Smuzhiyun NULL, /* SIOCIWFIRSTPRIV */
3268*4882a593Smuzhiyun };
3269*4882a593Smuzhiyun #endif /* STA_SUPPORT */
3270*4882a593Smuzhiyun
3271*4882a593Smuzhiyun /********************************************************
3272*4882a593Smuzhiyun Global Functions
3273*4882a593Smuzhiyun ********************************************************/
3274*4882a593Smuzhiyun
3275*4882a593Smuzhiyun #if WIRELESS_EXT > 14
3276*4882a593Smuzhiyun
3277*4882a593Smuzhiyun /**
3278*4882a593Smuzhiyun * @brief This function sends customized event to application.
3279*4882a593Smuzhiyun *
3280*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3281*4882a593Smuzhiyun * @param str A pointer to event string
3282*4882a593Smuzhiyun *
3283*4882a593Smuzhiyun * @return N/A
3284*4882a593Smuzhiyun */
woal_send_iwevcustom_event(moal_private * priv,char * str)3285*4882a593Smuzhiyun void woal_send_iwevcustom_event(moal_private *priv, char *str)
3286*4882a593Smuzhiyun {
3287*4882a593Smuzhiyun union iwreq_data iwrq;
3288*4882a593Smuzhiyun char buf[IW_CUSTOM_MAX];
3289*4882a593Smuzhiyun
3290*4882a593Smuzhiyun ENTER();
3291*4882a593Smuzhiyun /* Check register_netdevice is completed before sending*/
3292*4882a593Smuzhiyun if (priv->netdev->reg_state != NETREG_REGISTERED) {
3293*4882a593Smuzhiyun LEAVE();
3294*4882a593Smuzhiyun return;
3295*4882a593Smuzhiyun }
3296*4882a593Smuzhiyun
3297*4882a593Smuzhiyun memset(&iwrq, 0, sizeof(union iwreq_data));
3298*4882a593Smuzhiyun memset(buf, 0, sizeof(buf));
3299*4882a593Smuzhiyun
3300*4882a593Smuzhiyun snprintf(buf, sizeof(buf) - 1, "%s", str);
3301*4882a593Smuzhiyun
3302*4882a593Smuzhiyun iwrq.data.pointer = (t_u8 __user *)buf;
3303*4882a593Smuzhiyun iwrq.data.length = strlen(buf) + 1;
3304*4882a593Smuzhiyun
3305*4882a593Smuzhiyun /* Send Event to upper layer */
3306*4882a593Smuzhiyun wireless_send_event(priv->netdev, IWEVCUSTOM, &iwrq, buf);
3307*4882a593Smuzhiyun PRINTM(MINFO, "Wireless event %s is sent to application\n", str);
3308*4882a593Smuzhiyun
3309*4882a593Smuzhiyun LEAVE();
3310*4882a593Smuzhiyun return;
3311*4882a593Smuzhiyun }
3312*4882a593Smuzhiyun #endif
3313*4882a593Smuzhiyun
3314*4882a593Smuzhiyun #if WIRELESS_EXT >= 18
3315*4882a593Smuzhiyun /**
3316*4882a593Smuzhiyun * @brief This function sends mic error event to application.
3317*4882a593Smuzhiyun *
3318*4882a593Smuzhiyun * @param priv A pointer to moal_private structure
3319*4882a593Smuzhiyun * @param event MIC MERROR EVENT.
3320*4882a593Smuzhiyun *
3321*4882a593Smuzhiyun * @return N/A
3322*4882a593Smuzhiyun */
woal_send_mic_error_event(moal_private * priv,t_u32 event)3323*4882a593Smuzhiyun void woal_send_mic_error_event(moal_private *priv, t_u32 event)
3324*4882a593Smuzhiyun {
3325*4882a593Smuzhiyun union iwreq_data iwrq;
3326*4882a593Smuzhiyun struct iw_michaelmicfailure mic;
3327*4882a593Smuzhiyun
3328*4882a593Smuzhiyun ENTER();
3329*4882a593Smuzhiyun
3330*4882a593Smuzhiyun memset(&iwrq, 0, sizeof(iwrq));
3331*4882a593Smuzhiyun memset(&mic, 0, sizeof(mic));
3332*4882a593Smuzhiyun if (event == MLAN_EVENT_ID_FW_MIC_ERR_UNI)
3333*4882a593Smuzhiyun mic.flags = IW_MICFAILURE_PAIRWISE;
3334*4882a593Smuzhiyun else
3335*4882a593Smuzhiyun mic.flags = IW_MICFAILURE_GROUP;
3336*4882a593Smuzhiyun iwrq.data.pointer = (t_u8 __user *)&mic;
3337*4882a593Smuzhiyun iwrq.data.length = sizeof(mic);
3338*4882a593Smuzhiyun
3339*4882a593Smuzhiyun wireless_send_event(priv->netdev, IWEVMICHAELMICFAILURE, &iwrq,
3340*4882a593Smuzhiyun (char *)&mic);
3341*4882a593Smuzhiyun
3342*4882a593Smuzhiyun LEAVE();
3343*4882a593Smuzhiyun return;
3344*4882a593Smuzhiyun }
3345*4882a593Smuzhiyun #endif
3346*4882a593Smuzhiyun
3347*4882a593Smuzhiyun // clang-format off
3348*4882a593Smuzhiyun #ifdef STA_SUPPORT
3349*4882a593Smuzhiyun /** wlan_handler_def */
3350*4882a593Smuzhiyun struct iw_handler_def woal_handler_def = {
3351*4882a593Smuzhiyun .num_standard = ARRAY_SIZE(woal_handler),
3352*4882a593Smuzhiyun .num_private = ARRAY_SIZE(woal_private_handler),
3353*4882a593Smuzhiyun .num_private_args = ARRAY_SIZE(woal_private_args),
3354*4882a593Smuzhiyun .standard = (iw_handler *)woal_handler,
3355*4882a593Smuzhiyun .private = (iw_handler *)woal_private_handler,
3356*4882a593Smuzhiyun .private_args = (struct iw_priv_args *)woal_private_args,
3357*4882a593Smuzhiyun #if WIRELESS_EXT > 20
3358*4882a593Smuzhiyun .get_wireless_stats = woal_get_wireless_stats,
3359*4882a593Smuzhiyun #endif
3360*4882a593Smuzhiyun };
3361*4882a593Smuzhiyun // clang-format on
3362*4882a593Smuzhiyun
3363*4882a593Smuzhiyun /**
3364*4882a593Smuzhiyun * @brief Get wireless statistics
3365*4882a593Smuzhiyun *
3366*4882a593Smuzhiyun * @param dev A pointer to net_device structure
3367*4882a593Smuzhiyun *
3368*4882a593Smuzhiyun * @return A pointer to iw_statistics buf
3369*4882a593Smuzhiyun */
woal_get_wireless_stats(struct net_device * dev)3370*4882a593Smuzhiyun struct iw_statistics *woal_get_wireless_stats(struct net_device *dev)
3371*4882a593Smuzhiyun {
3372*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(dev);
3373*4882a593Smuzhiyun t_u16 wait_option = MOAL_IOCTL_WAIT;
3374*4882a593Smuzhiyun
3375*4882a593Smuzhiyun ENTER();
3376*4882a593Smuzhiyun
3377*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
3378*4882a593Smuzhiyun /*
3379*4882a593Smuzhiyun * Since schedule() is not allowed from an atomic context
3380*4882a593Smuzhiyun * such as when dev_base_lock for netdevices is acquired
3381*4882a593Smuzhiyun * for reading/writing in kernel before this call, HostCmd
3382*4882a593Smuzhiyun * is issued in non-blocking way in such contexts and
3383*4882a593Smuzhiyun * blocking in other cases.
3384*4882a593Smuzhiyun */
3385*4882a593Smuzhiyun if (in_atomic() || !write_can_lock(&dev_base_lock))
3386*4882a593Smuzhiyun wait_option = MOAL_NO_WAIT;
3387*4882a593Smuzhiyun #endif
3388*4882a593Smuzhiyun
3389*4882a593Smuzhiyun priv->w_stats.status = woal_get_mode(priv, wait_option);
3390*4882a593Smuzhiyun priv->w_stats.discard.retries = priv->stats.tx_errors;
3391*4882a593Smuzhiyun priv->w_stats.qual.qual = 0;
3392*4882a593Smuzhiyun
3393*4882a593Smuzhiyun /* Send RSSI command to get beacon RSSI/NF, valid only if associated */
3394*4882a593Smuzhiyun if (priv->media_connected == MTRUE) {
3395*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS ==
3396*4882a593Smuzhiyun woal_get_signal_info(priv, wait_option, NULL))
3397*4882a593Smuzhiyun priv->w_stats.qual.qual = woal_rssi_to_quality(
3398*4882a593Smuzhiyun (t_s16)(priv->w_stats.qual.level - 0x100));
3399*4882a593Smuzhiyun }
3400*4882a593Smuzhiyun #if WIRELESS_EXT > 18
3401*4882a593Smuzhiyun priv->w_stats.qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM);
3402*4882a593Smuzhiyun #else
3403*4882a593Smuzhiyun priv->w_stats.qual.updated |= 7;
3404*4882a593Smuzhiyun #endif
3405*4882a593Smuzhiyun if (!priv->w_stats.qual.noise && priv->media_connected == MTRUE)
3406*4882a593Smuzhiyun priv->w_stats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
3407*4882a593Smuzhiyun
3408*4882a593Smuzhiyun PRINTM(MINFO, "Link Quality = %#x\n", priv->w_stats.qual.qual);
3409*4882a593Smuzhiyun PRINTM(MINFO, "Signal Level = %#x\n", priv->w_stats.qual.level);
3410*4882a593Smuzhiyun PRINTM(MINFO, "Noise = %#x\n", priv->w_stats.qual.noise);
3411*4882a593Smuzhiyun priv->w_stats.discard.code = 0;
3412*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS != woal_get_stats_info(priv, wait_option, NULL))
3413*4882a593Smuzhiyun PRINTM(MERROR, "Error getting stats information\n");
3414*4882a593Smuzhiyun
3415*4882a593Smuzhiyun LEAVE();
3416*4882a593Smuzhiyun return &priv->w_stats;
3417*4882a593Smuzhiyun }
3418*4882a593Smuzhiyun #endif /* STA_SUPPORT */
3419