]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/staging/rtl8723au/core/rtw_mlme_ext.c
Merge tag 'nfc-next-4.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo...
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / rtl8723au / core / rtw_mlme_ext.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15 #define _RTW_MLME_EXT_C_
16
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <wifi.h>
20 #include <rtw_mlme_ext.h>
21 #include <wlan_bssdef.h>
22 #include <mlme_osdep.h>
23 #include <recv_osdep.h>
24 #include <linux/ieee80211.h>
25 #include <rtl8723a_hal.h>
26
27 static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
28 static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
29 static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
30 static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
31 static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
32 static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
33 static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
34 static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
35 static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
36 static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
37 static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
38
39 static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
40 static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
41 static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
42 static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
43 static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
44 static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
45 static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
46 static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
47
48 static void issue_assocreq(struct rtw_adapter *padapter);
49 static void issue_probereq(struct rtw_adapter *padapter,
50 struct cfg80211_ssid *pssid, u8 *da);
51 static int issue_probereq_ex(struct rtw_adapter *padapter,
52 struct cfg80211_ssid *pssid,
53 u8 *da, int try_cnt, int wait_ms);
54 static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da);
55 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
56 unsigned short status);
57 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
58 unsigned short reason, int try_cnt, int wait_ms);
59 static void start_clnt_assoc(struct rtw_adapter *padapter);
60 static void start_clnt_auth(struct rtw_adapter *padapter);
61 static void start_clnt_join(struct rtw_adapter *padapter);
62 static void start_create_ibss(struct rtw_adapter *padapter);
63 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
64 struct recv_frame *precv_frame);
65
66 #ifdef CONFIG_8723AU_AP_MODE
67 static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
68 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
69 struct sta_info *pstat, u16 pkt_type);
70 #endif
71
72 static struct mlme_handler mlme_sta_tbl[]={
73 {"OnAssocReq23a", &OnAssocReq23a},
74 {"OnAssocRsp23a", &OnAssocRsp23a},
75 {"OnReAssocReq", &OnAssocReq23a},
76 {"OnReAssocRsp", &OnAssocRsp23a},
77 {"OnProbeReq23a", &OnProbeReq23a},
78 {"OnProbeRsp23a", &OnProbeRsp23a},
79
80 /*----------------------------------------------------------
81 below 2 are reserved
82 -----------------------------------------------------------*/
83 {"DoReserved23a", &DoReserved23a},
84 {"DoReserved23a", &DoReserved23a},
85 {"OnBeacon23a", &OnBeacon23a},
86 {"OnATIM", &OnAtim23a},
87 {"OnDisassoc23a", &OnDisassoc23a},
88 {"OnAuth23a", &OnAuth23aClient23a},
89 {"OnDeAuth23a", &OnDeAuth23a},
90 {"OnAction23a", &OnAction23a},
91 };
92
93 static struct action_handler OnAction23a_tbl[]={
94 {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
95 {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
96 {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
97 {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
98 {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
99 {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
100 {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
101 {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
102 {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
103 };
104
105 static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
106
107 /**************************************************
108 OUI definitions for the vendor specific IE
109 ***************************************************/
110 unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
111 unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
112 unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
113 unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
114
115 unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
116 unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
117
118 static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
119
120 /********************************************************
121 MCS rate definitions
122 *********************************************************/
123 unsigned char MCS_rate_2R23A[16] = {
124 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
125 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
126 unsigned char MCS_rate_1R23A[16] = {
127 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
128 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
129
130 /********************************************************
131 ChannelPlan definitions
132 *********************************************************/
133
134 static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
135 /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
136 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
137 /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
138 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
139 /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
140 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
141 /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
142 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
143 /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
144 {{10, 11, 12, 13}, 4},
145 /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
146 {{}, 0},
147 };
148
149 static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
150 /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
151 {{}, 0},
152 /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
153 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
154 116, 120, 124, 128, 132, 136, 140}, 19},
155 /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
156 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
157 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
158 /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
159 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
160 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
161 /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
162 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
163 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
164 /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
165 {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
166 /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
167 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
168 /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
169 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
170 /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
171 {{149, 153, 157, 161, 165}, 5},
172 /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
173 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
174 /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
175 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
176 116, 136, 140, 149, 153, 157, 161, 165}, 20},
177 /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
178 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
179 116, 120, 124, 149, 153, 157, 161, 165}, 20},
180 /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
181 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
182 116, 120, 124, 128, 132, 136, 140}, 19},
183 /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
184 {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
185 /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
186 {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
187 /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
188 {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
189 153, 157, 161, 165}, 15},
190 /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
191 {{56, 60, 64, 149, 153, 157, 161, 165}, 8},
192
193 /* Driver self defined for old channel plan Compatible,
194 Remember to modify if have new channel plan definition ===== */
195 /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */
196 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
197 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
198 /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
199 {{36, 40, 44, 48}, 4},
200 /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
201 {{36, 40, 44, 48, 149, 153, 157, 161}, 8},
202 };
203
204 static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
205 /* 0x00 ~ 0x1F , Old Define ===== */
206 {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
207 {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
208 {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
209 {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
210 {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
211 {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
212 {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
213 {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
214 {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
215 {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
216 {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
217 {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
218 {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
219 {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
220 {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
221 {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
222 {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
223 {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
224 {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
225 {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
226 {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
227 {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
228 {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
229 {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
230 {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
231 {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
232 {0x00, 0x00}, /* 0x1A, */
233 {0x00, 0x00}, /* 0x1B, */
234 {0x00, 0x00}, /* 0x1C, */
235 {0x00, 0x00}, /* 0x1D, */
236 {0x00, 0x00}, /* 0x1E, */
237 {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
238 /* 0x20 ~ 0x7F , New Define ===== */
239 {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
240 {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
241 {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
242 {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
243 {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
244 {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
245 {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
246 {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
247 {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
248 {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
249 {0x00, 0x00}, /* 0x2A, */
250 {0x00, 0x00}, /* 0x2B, */
251 {0x00, 0x00}, /* 0x2C, */
252 {0x00, 0x00}, /* 0x2D, */
253 {0x00, 0x00}, /* 0x2E, */
254 {0x00, 0x00}, /* 0x2F, */
255 {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
256 {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
257 {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
258 {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
259 {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
260 {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
261 {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
262 {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
263 {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
264 {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
265 {0x00, 0x00}, /* 0x3A, */
266 {0x00, 0x00}, /* 0x3B, */
267 {0x00, 0x00}, /* 0x3C, */
268 {0x00, 0x00}, /* 0x3D, */
269 {0x00, 0x00}, /* 0x3E, */
270 {0x00, 0x00}, /* 0x3F, */
271 {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
272 {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
273 };
274
275 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
276 {0x03, 0x02}; /* use the conbination for max channel numbers */
277
278 static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
279 {
280 }
281
282 static struct fwevent wlanevents[] =
283 {
284 {0, &dummy_event_callback}, /*0*/
285 {0, NULL},
286 {0, NULL},
287 {0, NULL},
288 {0, NULL},
289 {0, NULL},
290 {0, NULL},
291 {0, NULL},
292 {0, &rtw_survey_event_cb23a}, /*8*/
293 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
294 {0, &rtw23a_joinbss_event_cb}, /*10*/
295 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
296 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
297 {0, &dummy_event_callback},
298 {0, &dummy_event_callback},
299 {0, NULL}, /*15*/
300 {0, NULL},
301 {0, NULL},
302 {0, NULL},
303 {0, &dummy_event_callback},
304 {0, NULL}, /*20*/
305 {0, NULL},
306 {0, NULL},
307 {0, &dummy_event_callback},
308 {0, NULL},
309 };
310
311
312 static void rtw_correct_TSF(struct rtw_adapter *padapter)
313 {
314 hw_var_set_correct_tsf(padapter);
315 }
316
317 static void
318 rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
319 {
320 pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
321 }
322
323 /*
324 * Search the @param channel_num in given @param channel_set
325 * @ch_set: the given channel set
326 * @ch: the given channel number
327 *
328 * return the index of channel_num in channel_set, -1 if not found
329 */
330 int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
331 {
332 int i;
333
334 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
335 if (ch == ch_set[i].ChannelNum)
336 break;
337 }
338
339 if (i >= ch_set[i].ChannelNum)
340 return -1;
341 return i;
342 }
343
344 /****************************************************************************
345
346 Following are the initialization functions for WiFi MLME
347
348 *****************************************************************************/
349
350 int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
351 {
352 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
353
354 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
355 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
356 return _SUCCESS;
357 }
358
359 static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter)
360 {
361 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
362 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
363 unsigned char mixed_datarate[NumRates] = {
364 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
365 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
366 _48M_RATE_, _54M_RATE_, 0xff};
367 unsigned char mixed_basicrate[NumRates] = {
368 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
369 _12M_RATE_, _24M_RATE_, 0xff,};
370
371 atomic_set(&pmlmeext->event_seq, 0);
372 /* reset to zero when disconnect at client mode */
373 pmlmeext->mgnt_seq = 0;
374
375 pmlmeext->cur_channel = padapter->registrypriv.channel;
376 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
377 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
378
379 pmlmeext->retry = 0;
380
381 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
382
383 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
384 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
385
386 if (pmlmeext->cur_channel > 14)
387 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
388 else
389 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
390
391 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
392 pmlmeext->sitesurvey_res.channel_idx = 0;
393 pmlmeext->sitesurvey_res.bss_cnt = 0;
394 pmlmeext->scan_abort = false;
395
396 pmlmeinfo->state = MSR_NOLINK;
397 pmlmeinfo->reauth_count = 0;
398 pmlmeinfo->reassoc_count = 0;
399 pmlmeinfo->link_count = 0;
400 pmlmeinfo->auth_seq = 0;
401 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
402 pmlmeinfo->key_index = 0;
403 pmlmeinfo->iv = 0;
404
405 pmlmeinfo->enc_algo = 0;
406 pmlmeinfo->authModeToggle = 0;
407
408 memset(pmlmeinfo->chg_txt, 0, 128);
409
410 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
411 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
412
413 pmlmeinfo->dialogToken = 0;
414
415 pmlmeext->action_public_rxseq = 0xffff;
416 pmlmeext->action_public_dialog_token = 0xff;
417 }
418
419 static int has_channel(struct rt_channel_info *channel_set,
420 u8 chanset_size, u8 chan) {
421 int i;
422
423 for (i = 0; i < chanset_size; i++) {
424 if (channel_set[i].ChannelNum == chan)
425 return 1;
426 }
427
428 return 0;
429 }
430
431 static void init_channel_list(struct rtw_adapter *padapter,
432 struct rt_channel_info *channel_set,
433 u8 chanset_size,
434 struct p2p_channels *channel_list)
435 {
436 struct p2p_oper_class_map op_class[] = {
437 { IEEE80211G, 81, 1, 13, 1, BW20 },
438 { IEEE80211G, 82, 14, 14, 1, BW20 },
439 { IEEE80211A, 115, 36, 48, 4, BW20 },
440 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
441 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
442 { IEEE80211A, 124, 149, 161, 4, BW20 },
443 { IEEE80211A, 125, 149, 169, 4, BW20 },
444 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
445 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
446 { -1, 0, 0, 0, 0, BW20 }
447 };
448
449 int cla, op;
450
451 cla = 0;
452
453 for (op = 0; op_class[op].op_class; op++) {
454 u8 ch;
455 struct p2p_oper_class_map *o = &op_class[op];
456 struct p2p_reg_class *reg = NULL;
457
458 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
459 if (!has_channel(channel_set, chanset_size, ch))
460 continue;
461
462 if ((0 == padapter->registrypriv.ht_enable) &&
463 (o->inc == 8))
464 continue;
465
466 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
467 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
468 continue;
469
470 if (reg == NULL) {
471 reg = &channel_list->reg_class[cla];
472 cla++;
473 reg->reg_class = o->op_class;
474 reg->channels = 0;
475 }
476 reg->channel[reg->channels] = ch;
477 reg->channels++;
478 }
479 }
480 channel_list->reg_classes = cla;
481 }
482
483 static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan,
484 struct rt_channel_info *c_set)
485 {
486 u8 i, ch_size = 0;
487 u8 b5GBand = false, b2_4GBand = false;
488 u8 Index2G = 0, Index5G = 0;
489
490 memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
491
492 if (cplan >= RT_CHANNEL_DOMAIN_MAX &&
493 cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
494 DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan);
495 return ch_size;
496 }
497
498 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
499 b2_4GBand = true;
500 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
501 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
502 else
503 Index2G = RTW_ChannelPlanMap[cplan].Index2G;
504 }
505
506 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
507 b5GBand = true;
508 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
509 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
510 else
511 Index5G = RTW_ChannelPlanMap[cplan].Index5G;
512 }
513
514 if (b2_4GBand) {
515 for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
516 c_set[ch_size].ChannelNum =
517 RTW_ChannelPlan2G[Index2G].Channel[i];
518
519 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
520 /* Channel 1~11 is active, and 12~14 is passive */
521 RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) {
522 if (c_set[ch_size].ChannelNum >= 1 &&
523 c_set[ch_size].ChannelNum <= 11)
524 c_set[ch_size].ScanType = SCAN_ACTIVE;
525 else if (c_set[ch_size].ChannelNum >= 12 &&
526 c_set[ch_size].ChannelNum <= 14)
527 c_set[ch_size].ScanType = SCAN_PASSIVE;
528 } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan ||
529 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan ||
530 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
531 /* channel 12~13, passive scan */
532 if (c_set[ch_size].ChannelNum <= 11)
533 c_set[ch_size].ScanType = SCAN_ACTIVE;
534 else
535 c_set[ch_size].ScanType = SCAN_PASSIVE;
536 } else
537 c_set[ch_size].ScanType = SCAN_ACTIVE;
538
539 ch_size++;
540 }
541 }
542
543 if (b5GBand) {
544 for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) {
545 if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 ||
546 RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) {
547 c_set[ch_size].ChannelNum =
548 RTW_ChannelPlan5G[Index5G].Channel[i];
549 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) {
550 /* passive scan for all 5G channels */
551 c_set[ch_size].ScanType =
552 SCAN_PASSIVE;
553 } else
554 c_set[ch_size].ScanType =
555 SCAN_ACTIVE;
556 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
557 "%d\n", __func__, ch_size,
558 c_set[ch_size].ChannelNum);
559 ch_size++;
560 }
561 }
562 }
563
564 return ch_size;
565 }
566
567 int init_mlme_ext_priv23a(struct rtw_adapter *padapter)
568 {
569 struct registry_priv *pregistrypriv = &padapter->registrypriv;
570 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
571 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
572 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
573
574 pmlmeext->padapter = padapter;
575
576 init_mlme_ext_priv23a_value(padapter);
577 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
578
579 init_mlme_ext_timer23a(padapter);
580
581 #ifdef CONFIG_8723AU_AP_MODE
582 init_mlme_ap_info23a(padapter);
583 #endif
584
585 pmlmeext->max_chan_nums = init_channel_set(padapter,
586 pmlmepriv->ChannelPlan,
587 pmlmeext->channel_set);
588 init_channel_list(padapter, pmlmeext->channel_set,
589 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
590
591 pmlmeext->chan_scan_time = SURVEY_TO;
592 pmlmeext->mlmeext_init = true;
593
594 pmlmeext->active_keep_alive_check = true;
595 return _SUCCESS;
596 }
597
598 void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
599 {
600 struct rtw_adapter *padapter = pmlmeext->padapter;
601
602 if (!padapter)
603 return;
604
605 if (padapter->bDriverStopped == true) {
606 del_timer_sync(&pmlmeext->survey_timer);
607 del_timer_sync(&pmlmeext->link_timer);
608 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
609 }
610 }
611
612 static void
613 _mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
614 struct recv_frame *precv_frame)
615 {
616 struct sk_buff *skb = precv_frame->pkt;
617 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
618
619 if (ptable->func) {
620 /* receive the frames that ra(a1) is my address
621 or ra(a1) is bc address. */
622 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
623 !is_broadcast_ether_addr(hdr->addr1))
624 return;
625
626 ptable->func(padapter, precv_frame);
627 }
628 }
629
630 void mgt_dispatcher23a(struct rtw_adapter *padapter,
631 struct recv_frame *precv_frame)
632 {
633 struct mlme_handler *ptable;
634 #ifdef CONFIG_8723AU_AP_MODE
635 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
636 #endif /* CONFIG_8723AU_AP_MODE */
637 struct sk_buff *skb = precv_frame->pkt;
638 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
639 struct sta_info *psta;
640 u16 stype;
641 int index;
642
643 if (!ieee80211_is_mgmt(mgmt->frame_control))
644 return;
645
646 /* receive the frames that ra(a1) is my address or ra(a1) is
647 bc address. */
648 if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
649 !is_broadcast_ether_addr(mgmt->da))
650 return;
651
652 ptable = mlme_sta_tbl;
653
654 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
655 index = stype >> 4;
656
657 if (index > 13) {
658 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
659 "Currently we do not support reserved sub-fr-type =%d\n",
660 index);
661 return;
662 }
663 ptable += index;
664
665 psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
666
667 if (psta) {
668 if (ieee80211_has_retry(mgmt->frame_control)) {
669 if (precv_frame->attrib.seq_num ==
670 psta->RxMgmtFrameSeqNum) {
671 /* drop the duplicate management frame */
672 DBG_8723A("Drop duplicate management frame "
673 "with seq_num = %d.\n",
674 precv_frame->attrib.seq_num);
675 return;
676 }
677 }
678 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
679 }
680
681 #ifdef CONFIG_8723AU_AP_MODE
682 switch (stype) {
683 case IEEE80211_STYPE_AUTH:
684 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
685 ptable->func = &OnAuth23a;
686 else
687 ptable->func = &OnAuth23aClient23a;
688 /* pass through */
689 case IEEE80211_STYPE_ASSOC_REQ:
690 case IEEE80211_STYPE_REASSOC_REQ:
691 _mgt_dispatcher23a(padapter, ptable, precv_frame);
692 break;
693 case IEEE80211_STYPE_PROBE_REQ:
694 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
695 _mgt_dispatcher23a(padapter, ptable, precv_frame);
696 else
697 _mgt_dispatcher23a(padapter, ptable, precv_frame);
698 break;
699 case IEEE80211_STYPE_BEACON:
700 _mgt_dispatcher23a(padapter, ptable, precv_frame);
701 break;
702 case IEEE80211_STYPE_ACTION:
703 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
704 _mgt_dispatcher23a(padapter, ptable, precv_frame);
705 break;
706 default:
707 _mgt_dispatcher23a(padapter, ptable, precv_frame);
708 break;
709 }
710 #else
711 _mgt_dispatcher23a(padapter, ptable, precv_frame);
712 #endif
713 }
714
715 /****************************************************************************
716
717 Following are the callback functions for each subtype of the management frames
718
719 *****************************************************************************/
720
721 static int
722 OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
723 {
724 const u8 *ie;
725 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
726 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
727 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
728 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
729 struct sk_buff *skb = precv_frame->pkt;
730 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
731 int len = skb->len;
732
733 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
734 return _SUCCESS;
735
736 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
737 !check_fwstate(pmlmepriv,
738 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
739 return _SUCCESS;
740
741 if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
742 printk(KERN_WARNING "%s: Received non probe request frame\n",
743 __func__);
744 return _FAIL;
745 }
746
747 len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
748
749 ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
750
751 /* check (wildcard) SSID */
752 if (!ie)
753 goto out;
754
755 if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
756 (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
757 return _SUCCESS;
758 }
759
760 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
761 pmlmepriv->cur_network.join_res)
762 issue_probersp(padapter, mgmt->sa);
763
764 out:
765 return _SUCCESS;
766 }
767
768 static int
769 OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
770 {
771 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
772
773 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
774 report_survey_event23a(padapter, precv_frame);
775 return _SUCCESS;
776 }
777
778 return _SUCCESS;
779 }
780
781 static int
782 OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
783 {
784 int cam_idx;
785 struct sta_info *psta;
786 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
787 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
788 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
789 struct sta_priv *pstapriv = &padapter->stapriv;
790 struct sk_buff *skb = precv_frame->pkt;
791 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
792 int pkt_len = skb->len;
793 struct wlan_bssid_ex *pbss;
794 int ret = _SUCCESS;
795 u8 *p, *pie;
796 int pie_len;
797 u32 ielen = 0;
798
799 pie = mgmt->u.beacon.variable;
800 pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
801 p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len);
802 if (p && ielen > 0) {
803 if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
804 /* Invalid value 0x2D is detected in Extended Supported
805 * Rates (ESR) IE. Try to fix the IE length to avoid
806 * failed Beacon parsing.
807 */
808 DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
809 "Beacon of BSSID: %pM. Fix the length of "
810 "ESR IE to avoid failed Beacon parsing.\n",
811 mgmt->bssid);
812 p[1] = ielen - 1;
813 }
814 }
815
816 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
817 report_survey_event23a(padapter, precv_frame);
818 return _SUCCESS;
819 }
820
821 if (!ether_addr_equal(mgmt->bssid,
822 get_my_bssid23a(&pmlmeinfo->network)))
823 goto out;
824
825 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
826 /* we should update current network before auth,
827 or some IE is wrong */
828 pbss = collect_bss_info(padapter, precv_frame);
829 if (pbss) {
830 update_network23a(&pmlmepriv->cur_network.network, pbss,
831 padapter, true);
832 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
833 kfree(pbss);
834 }
835
836 /* check the vendor of the assoc AP */
837 pmlmeinfo->assoc_AP_vendor =
838 check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len -
839 offsetof(struct ieee80211_mgmt, u));
840
841 /* update TSF Value */
842 rtw_update_TSF(pmlmeext, mgmt);
843
844 /* start auth */
845 start_clnt_auth(padapter);
846
847 return _SUCCESS;
848 }
849
850 if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
851 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
852 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
853 if (psta) {
854 ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
855 if (ret != _SUCCESS) {
856 DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
857 "disconnect now\n");
858 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
859 return _SUCCESS;
860 }
861 /* update WMM, ERP in the beacon */
862 /* todo: the timer is used instead of
863 the number of the beacon received */
864 if ((sta_rx_pkts(psta) & 0xf) == 0) {
865 /* DBG_8723A("update_bcn_info\n"); */
866 update_beacon23a_info(padapter, mgmt,
867 pkt_len, psta);
868 }
869 }
870 } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
871 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
872 if (psta) {
873 /* update WMM, ERP in the beacon */
874 /* todo: the timer is used instead of the
875 number of the beacon received */
876 if ((sta_rx_pkts(psta) & 0xf) == 0) {
877 /* DBG_8723A("update_bcn_info\n"); */
878 update_beacon23a_info(padapter, mgmt,
879 pkt_len, psta);
880 }
881 } else {
882 /* allocate a new CAM entry for IBSS station */
883 cam_idx = allocate_fw_sta_entry23a(padapter);
884 if (cam_idx == NUM_STA)
885 goto out;
886
887 /* get supported rate */
888 if (update_sta_support_rate23a(padapter, pie, pie_len,
889 cam_idx) == _FAIL) {
890 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
891 goto out;
892 }
893
894 /* update TSF Value */
895 rtw_update_TSF(pmlmeext, mgmt);
896
897 /* report sta add event */
898 report_add_sta_event23a(padapter, mgmt->sa,
899 cam_idx);
900 }
901 }
902
903 out:
904
905 return _SUCCESS;
906 }
907
908 #ifdef CONFIG_8723AU_AP_MODE
909 static int
910 OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
911 {
912 static struct sta_info stat;
913 struct sta_info *pstat = NULL;
914 struct sta_priv *pstapriv = &padapter->stapriv;
915 struct security_priv *psecuritypriv = &padapter->securitypriv;
916 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
917 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
918 struct sk_buff *skb = precv_frame->pkt;
919 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
920 u8 *pframe;
921 const u8 *p;
922 unsigned char *sa;
923 u16 auth_mode, seq, algorithm;
924 int status, len = skb->len;
925
926 if ((pmlmeinfo->state & 0x03) != MSR_AP)
927 return _FAIL;
928
929 DBG_8723A("+OnAuth23a\n");
930
931 sa = mgmt->sa;
932
933 auth_mode = psecuritypriv->dot11AuthAlgrthm;
934
935 pframe = mgmt->u.auth.variable;
936 len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
937
938 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
939 algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
940
941 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
942
943 if (auth_mode == 2 &&
944 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 &&
945 psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104)
946 auth_mode = 0;
947
948 /* rx a shared-key auth but shared not enabled, or */
949 /* rx a open-system auth but shared-key is enabled */
950 if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
951 (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
952 DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
953 "=%d] %02X%02X%02X%02X%02X%02X\n",
954 algorithm, auth_mode,
955 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
956
957 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
958
959 goto auth_fail;
960 }
961
962 if (rtw_access_ctrl23a(padapter, sa) == false) {
963 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
964 goto auth_fail;
965 }
966
967 pstat = rtw_get_stainfo23a(pstapriv, sa);
968 if (!pstat) {
969 /* allocate a new one */
970 DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
971 pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
972 if (!pstat) {
973 DBG_8723A(" Exceed the upper limit of supported "
974 "clients...\n");
975 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
976 goto auth_fail;
977 }
978
979 pstat->state = WIFI_FW_AUTH_NULL;
980 pstat->auth_seq = 0;
981
982 /* pstat->flags = 0; */
983 /* pstat->capability = 0; */
984 } else {
985 spin_lock_bh(&pstapriv->asoc_list_lock);
986 if (!list_empty(&pstat->asoc_list)) {
987 list_del_init(&pstat->asoc_list);
988 pstapriv->asoc_list_cnt--;
989 if (pstat->expire_to > 0) {
990 /* TODO: STA re_auth within expire_to */
991 }
992 }
993 spin_unlock_bh(&pstapriv->asoc_list_lock);
994
995 if (seq == 1) {
996 /* TODO: STA re_auth and auth timeout */
997 }
998 }
999
1000 spin_lock_bh(&pstapriv->auth_list_lock);
1001 if (list_empty(&pstat->auth_list)) {
1002 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1003 pstapriv->auth_list_cnt++;
1004 }
1005 spin_unlock_bh(&pstapriv->auth_list_lock);
1006
1007 if (pstat->auth_seq == 0)
1008 pstat->expire_to = pstapriv->auth_to;
1009
1010 if ((pstat->auth_seq + 1) != seq) {
1011 DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
1012 "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
1013 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1014 goto auth_fail;
1015 }
1016
1017 if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
1018 if (seq == 1) {
1019 pstat->state &= ~WIFI_FW_AUTH_NULL;
1020 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1021 pstat->expire_to = pstapriv->assoc_to;
1022 pstat->authalg = algorithm;
1023 } else {
1024 DBG_8723A("(2)auth rejected because out of seq "
1025 "[rx_seq =%d, exp_seq =%d]!\n",
1026 seq, pstat->auth_seq+1);
1027 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1028 goto auth_fail;
1029 }
1030 } else { /* shared system or auto authentication */
1031 if (seq == 1) {
1032 /* prepare for the challenging txt... */
1033 pstat->state &= ~WIFI_FW_AUTH_NULL;
1034 pstat->state |= WIFI_FW_AUTH_STATE;
1035 pstat->authalg = algorithm;
1036 pstat->auth_seq = 2;
1037 } else if (seq == 3) {
1038 /* checking for challenging txt... */
1039 DBG_8723A("checking for challenging txt...\n");
1040
1041 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
1042 if (!p || p[1] <= 0) {
1043 DBG_8723A("auth rejected because challenge "
1044 "failure!(1)\n");
1045 status = WLAN_STATUS_CHALLENGE_FAIL;
1046 goto auth_fail;
1047 }
1048
1049 if (!memcmp(p + 2, pstat->chg_txt, 128)) {
1050 pstat->state &= ~WIFI_FW_AUTH_STATE;
1051 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1052 /* challenging txt is correct... */
1053 pstat->expire_to = pstapriv->assoc_to;
1054 } else {
1055 DBG_8723A("auth rejected because challenge "
1056 "failure!\n");
1057 status = WLAN_STATUS_CHALLENGE_FAIL;
1058 goto auth_fail;
1059 }
1060 } else {
1061 DBG_8723A("(3)auth rejected because out of seq "
1062 "[rx_seq =%d, exp_seq =%d]!\n",
1063 seq, pstat->auth_seq+1);
1064 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1065 goto auth_fail;
1066 }
1067 }
1068
1069 /* Now, we are going to issue_auth... */
1070 pstat->auth_seq = seq + 1;
1071
1072 issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS);
1073
1074 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1075 pstat->auth_seq = 0;
1076
1077 return _SUCCESS;
1078
1079 auth_fail:
1080
1081 if (pstat)
1082 rtw_free_stainfo23a(padapter, pstat);
1083
1084 pstat = &stat;
1085 memset((char *)pstat, '\0', sizeof(stat));
1086 pstat->auth_seq = 2;
1087 ether_addr_copy(pstat->hwaddr, sa);
1088
1089 issue_auth(padapter, pstat, (unsigned short)status);
1090
1091 return _FAIL;
1092 }
1093 #endif
1094
1095 static int
1096 OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1097 {
1098 unsigned int seq, status, algthm;
1099 unsigned int go2asoc = 0;
1100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1101 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1102 struct sk_buff *skb = precv_frame->pkt;
1103 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1104 const u8 *p;
1105 u8 *pie;
1106 int plen = skb->len;
1107
1108 DBG_8723A("%s\n", __func__);
1109
1110 /* check A1 matches or not */
1111 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
1112 return _SUCCESS;
1113
1114 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1115 return _SUCCESS;
1116
1117 pie = mgmt->u.auth.variable;
1118 plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
1119
1120 algthm = le16_to_cpu(mgmt->u.auth.auth_alg);
1121 seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
1122 status = le16_to_cpu(mgmt->u.auth.status_code);
1123
1124 if (status) {
1125 DBG_8723A("clnt auth fail, status: %d\n", status);
1126 /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1127 if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
1128 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1129 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1130 else
1131 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1132 /* pmlmeinfo->reauth_count = 0; */
1133 }
1134
1135 set_link_timer(pmlmeext, 1);
1136 goto authclnt_fail;
1137 }
1138
1139 if (seq == 2) {
1140 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1141 /* legendary shared system */
1142 p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
1143
1144 if (!p) {
1145 /* DBG_8723A("marc: no challenge text?\n"); */
1146 goto authclnt_fail;
1147 }
1148
1149 memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
1150 pmlmeinfo->auth_seq = 3;
1151 issue_auth(padapter, NULL, 0);
1152 set_link_timer(pmlmeext, REAUTH_TO);
1153
1154 return _SUCCESS;
1155 } else {
1156 /* open system */
1157 go2asoc = 1;
1158 }
1159 } else if (seq == 4) {
1160 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1161 go2asoc = 1;
1162 else
1163 goto authclnt_fail;
1164 } else {
1165 /* this is also illegal */
1166 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
1167 seq); */
1168 goto authclnt_fail;
1169 }
1170
1171 if (go2asoc) {
1172 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1173 start_clnt_assoc(padapter);
1174 return _SUCCESS;
1175 }
1176
1177 authclnt_fail:
1178
1179 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1180
1181 return _FAIL;
1182 }
1183
1184 #ifdef CONFIG_8723AU_AP_MODE
1185 static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
1186 {
1187 unsigned int oui;
1188
1189 /* first 3 bytes in vendor specific information element are the IEEE
1190 * OUI of the vendor. The following byte is used a vendor specific
1191 * sub-type. */
1192 if (elen < 4) {
1193 DBG_8723A("short vendor specific information element "
1194 "ignored (len =%i)\n", elen);
1195 return -EINVAL;
1196 }
1197
1198 oui = RTW_GET_BE24(pos);
1199 switch (oui) {
1200 case WLAN_OUI_MICROSOFT:
1201 /* Microsoft/Wi-Fi information elements are further typed and
1202 * subtyped */
1203 switch (pos[3]) {
1204 case WLAN_OUI_TYPE_MICROSOFT_WPA:
1205 /* Microsoft OUI (00:50:F2) with OUI Type 1:
1206 * real WPA information element */
1207 break;
1208 case WLAN_OUI_TYPE_MICROSOFT_WMM:
1209 if (elen < 5) {
1210 DBG_8723A("short WME information element "
1211 "ignored (len =%i)\n", elen);
1212 return -EINVAL;
1213 }
1214 switch (pos[4]) {
1215 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
1216 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
1217 break;
1218 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
1219 break;
1220 default:
1221 DBG_8723A("unknown WME information element "
1222 "ignored (subtype =%d len =%i)\n",
1223 pos[4], elen);
1224 return -EINVAL;
1225 }
1226 break;
1227 case WLAN_OUI_TYPE_MICROSOFT_WPS:
1228 /* Wi-Fi Protected Setup (WPS) IE */
1229 break;
1230 default:
1231 DBG_8723A("Unknown Microsoft information element "
1232 "ignored (type =%d len =%i)\n",
1233 pos[3], elen);
1234 return -EINVAL;
1235 }
1236 break;
1237
1238 case OUI_BROADCOM:
1239 switch (pos[3]) {
1240 case VENDOR_HT_CAPAB_OUI_TYPE:
1241 break;
1242 default:
1243 DBG_8723A("Unknown Broadcom information element "
1244 "ignored (type =%d len =%i)\n", pos[3], elen);
1245 return -EINVAL;
1246 }
1247 break;
1248
1249 default:
1250 DBG_8723A("unknown vendor specific information element "
1251 "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
1252 pos[0], pos[1], pos[2], elen);
1253 return -EINVAL;
1254 }
1255
1256 return 0;
1257 }
1258
1259 static int rtw_validate_frame_ies(const u8 *start, uint len)
1260 {
1261 const u8 *pos = start;
1262 int left = len;
1263 int unknown = 0;
1264
1265 while (left >= 2) {
1266 u8 id, elen;
1267
1268 id = *pos++;
1269 elen = *pos++;
1270 left -= 2;
1271
1272 if (elen > left) {
1273 DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
1274 "left =%i)\n", __func__, id, elen, left);
1275 return -EINVAL;
1276 }
1277
1278 switch (id) {
1279 case WLAN_EID_SSID:
1280 case WLAN_EID_SUPP_RATES:
1281 case WLAN_EID_FH_PARAMS:
1282 case WLAN_EID_DS_PARAMS:
1283 case WLAN_EID_CF_PARAMS:
1284 case WLAN_EID_TIM:
1285 case WLAN_EID_IBSS_PARAMS:
1286 case WLAN_EID_CHALLENGE:
1287 case WLAN_EID_ERP_INFO:
1288 case WLAN_EID_EXT_SUPP_RATES:
1289 break;
1290 case WLAN_EID_VENDOR_SPECIFIC:
1291 if (rtw_validate_vendor_specific_ies(pos, elen))
1292 unknown++;
1293 break;
1294 case WLAN_EID_RSN:
1295 case WLAN_EID_PWR_CAPABILITY:
1296 case WLAN_EID_SUPPORTED_CHANNELS:
1297 case WLAN_EID_MOBILITY_DOMAIN:
1298 case WLAN_EID_FAST_BSS_TRANSITION:
1299 case WLAN_EID_TIMEOUT_INTERVAL:
1300 case WLAN_EID_HT_CAPABILITY:
1301 case WLAN_EID_HT_OPERATION:
1302 default:
1303 unknown++;
1304 DBG_8723A("%s IEEE 802.11 ignored unknown element "
1305 "(id =%d elen =%d)\n", __func__, id, elen);
1306 break;
1307 }
1308
1309 left -= elen;
1310 pos += elen;
1311 }
1312
1313 if (left)
1314 return -EINVAL;
1315
1316 return 0;
1317 }
1318 #endif
1319
1320 static int
1321 OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1322 {
1323 #ifdef CONFIG_8723AU_AP_MODE
1324 u16 capab_info, listen_interval;
1325 struct sta_info *pstat;
1326 unsigned char reassoc;
1327 int i, wpa_ie_len, left;
1328 unsigned char supportRate[16];
1329 int supportRateNum;
1330 unsigned short status = WLAN_STATUS_SUCCESS;
1331 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1332 struct security_priv *psecuritypriv = &padapter->securitypriv;
1333 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1334 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1335 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
1336 struct sta_priv *pstapriv = &padapter->stapriv;
1337 struct sk_buff *skb = precv_frame->pkt;
1338 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1339 const u8 *pos, *p, *wpa_ie, *wps_ie;
1340 u8 *pframe = skb->data;
1341 uint pkt_len = skb->len;
1342 int r;
1343
1344 if ((pmlmeinfo->state & 0x03) != MSR_AP)
1345 return _FAIL;
1346
1347 left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
1348 if (ieee80211_is_assoc_req(mgmt->frame_control)) {
1349 reassoc = 0;
1350 pos = mgmt->u.assoc_req.variable;
1351 left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
1352 } else { /* WIFI_REASSOCREQ */
1353 reassoc = 1;
1354 pos = mgmt->u.reassoc_req.variable;
1355 left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
1356 }
1357
1358 if (left < 0) {
1359 DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
1360 "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
1361 return _FAIL;
1362 }
1363
1364 pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1365 if (!pstat) {
1366 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1367 goto asoc_class2_error;
1368 }
1369
1370 /* These two are located at the same offsets whether it's an
1371 * assoc_req or a reassoc_req */
1372 capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info);
1373 listen_interval =
1374 get_unaligned_le16(&mgmt->u.assoc_req.listen_interval);
1375
1376 DBG_8723A("%s\n", __func__);
1377
1378 /* check if this stat has been successfully authenticated/assocated */
1379 if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
1380 if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
1381 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1382 goto asoc_class2_error;
1383 } else {
1384 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1385 pstat->state |= WIFI_FW_ASSOC_STATE;
1386 }
1387 } else {
1388 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1389 pstat->state |= WIFI_FW_ASSOC_STATE;
1390 }
1391
1392 pstat->capability = capab_info;
1393
1394 /* now parse all ieee802_11 ie to point to elems */
1395
1396 if (rtw_validate_frame_ies(pos, left)) {
1397 DBG_8723A("STA %pM sent invalid association request\n",
1398 pstat->hwaddr);
1399 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1400 goto OnAssocReq23aFail;
1401 }
1402
1403 /* now we should check all the fields... */
1404 /* checking SSID */
1405 p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
1406 if (!p || p[1] == 0) {
1407 /* broadcast ssid, however it is not allowed in assocreq */
1408 DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
1409 pstat->hwaddr);
1410 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1411 goto OnAssocReq23aFail;
1412 } else {
1413 /* check if ssid match */
1414 if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
1415 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1416
1417 if (p[1] != cur->Ssid.ssid_len)
1418 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1419 }
1420
1421 if (status != WLAN_STATUS_SUCCESS)
1422 goto OnAssocReq23aFail;
1423
1424 /* check if the supported rate is ok */
1425 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left);
1426 if (!p) {
1427 DBG_8723A("Rx a sta assoc-req which supported rate is "
1428 "empty!\n");
1429 /* use our own rate set as statoin used */
1430 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1431 /* supportRateNum = AP_BSSRATE_LEN; */
1432
1433 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1434 goto OnAssocReq23aFail;
1435 } else {
1436 memcpy(supportRate, p + 2, p[1]);
1437 supportRateNum = p[1];
1438
1439 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
1440 if (p) {
1441 if (supportRateNum <= sizeof(supportRate)) {
1442 memcpy(supportRate+supportRateNum, p + 2, p[1]);
1443 supportRateNum += p[1];
1444 }
1445 }
1446 }
1447
1448 /* todo: mask supportRate between AP & STA -> move to update raid */
1449 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1450
1451 /* update station supportRate */
1452 pstat->bssratelen = supportRateNum;
1453 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1454 Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1455
1456 /* check RSN/WPA/WPS */
1457 pstat->dot8021xalg = 0;
1458 pstat->wpa_psk = 0;
1459 pstat->wpa_group_cipher = 0;
1460 pstat->wpa2_group_cipher = 0;
1461 pstat->wpa_pairwise_cipher = 0;
1462 pstat->wpa2_pairwise_cipher = 0;
1463 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1464
1465 wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left);
1466 if (!wpa_ie)
1467 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1468 WLAN_OUI_TYPE_MICROSOFT_WPA,
1469 pos, left);
1470 if (wpa_ie) {
1471 int group_cipher = 0, pairwise_cipher = 0;
1472
1473 wpa_ie_len = wpa_ie[1];
1474 if (psecuritypriv->wpa_psk & BIT(1)) {
1475 r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2,
1476 &group_cipher,
1477 &pairwise_cipher, NULL);
1478 if (r == _SUCCESS) {
1479 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1480 pstat->wpa_psk |= BIT(1);
1481
1482 pstat->wpa2_group_cipher = group_cipher &
1483 psecuritypriv->wpa2_group_cipher;
1484 pstat->wpa2_pairwise_cipher = pairwise_cipher &
1485 psecuritypriv->wpa2_pairwise_cipher;
1486 } else
1487 status = WLAN_STATUS_INVALID_IE;
1488 } else if (psecuritypriv->wpa_psk & BIT(0)) {
1489 r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2,
1490 &group_cipher, &pairwise_cipher,
1491 NULL);
1492 if (r == _SUCCESS) {
1493 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1494 pstat->wpa_psk |= BIT(0);
1495
1496 pstat->wpa_group_cipher = group_cipher &
1497 psecuritypriv->wpa_group_cipher;
1498 pstat->wpa_pairwise_cipher = pairwise_cipher &
1499 psecuritypriv->wpa_pairwise_cipher;
1500 } else
1501 status = WLAN_STATUS_INVALID_IE;
1502 } else {
1503 wpa_ie = NULL;
1504 wpa_ie_len = 0;
1505 }
1506 if (wpa_ie && status == WLAN_STATUS_SUCCESS) {
1507 if (!pstat->wpa_group_cipher)
1508 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1509
1510 if (!pstat->wpa_pairwise_cipher)
1511 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1512 }
1513 }
1514
1515 if (status != WLAN_STATUS_SUCCESS)
1516 goto OnAssocReq23aFail;
1517
1518 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1519
1520 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1521 WLAN_OUI_TYPE_MICROSOFT_WPS,
1522 pos, left);
1523
1524 if (!wpa_ie) {
1525 if (wps_ie) {
1526 DBG_8723A("STA included WPS IE in (Re)Association "
1527 "Request - assume WPS is used\n");
1528 pstat->flags |= WLAN_STA_WPS;
1529 } else {
1530 DBG_8723A("STA did not include WPA/RSN IE in (Re)"
1531 "Association Request - possible WPS use\n");
1532 pstat->flags |= WLAN_STA_MAYBE_WPS;
1533 }
1534 } else {
1535 int copy_len;
1536
1537 if (psecuritypriv->wpa_psk == 0) {
1538 DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
1539 pstat->hwaddr);
1540
1541 status = WLAN_STATUS_INVALID_IE;
1542
1543 goto OnAssocReq23aFail;
1544 }
1545
1546 if (wps_ie) {
1547 DBG_8723A("STA included WPS IE in (Re)Association "
1548 "Request - WPS is used\n");
1549 pstat->flags |= WLAN_STA_WPS;
1550 copy_len = 0;
1551 } else {
1552 copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
1553 sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
1554 }
1555
1556 if (copy_len > 0)
1557 memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
1558 }
1559
1560 /* check if there is WMM IE & support WWM-PS */
1561 pstat->flags &= ~WLAN_STA_WME;
1562 pstat->qos_option = 0;
1563 pstat->qos_info = 0;
1564 pstat->has_legacy_ac = true;
1565 pstat->uapsd_vo = 0;
1566 pstat->uapsd_vi = 0;
1567 pstat->uapsd_be = 0;
1568 pstat->uapsd_bk = 0;
1569 if (pmlmepriv->qos_option) {
1570 const u8 *end = pos + left;
1571
1572 p = pos;
1573
1574 for (;;) {
1575 left = end - p;
1576 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1577 WLAN_OUI_TYPE_MICROSOFT_WMM,
1578 p, left);
1579 if (p) {
1580 pstat->flags |= WLAN_STA_WME;
1581
1582 pstat->qos_option = 1;
1583 pstat->qos_info = *(p + 8);
1584
1585 pstat->max_sp_len =
1586 (pstat->qos_info >> 5) & 0x3;
1587
1588 if ((pstat->qos_info & 0xf) != 0xf)
1589 pstat->has_legacy_ac = true;
1590 else
1591 pstat->has_legacy_ac = false;
1592
1593 if (pstat->qos_info & 0xf) {
1594 if (pstat->qos_info & BIT(0))
1595 pstat->uapsd_vo = BIT(0)|BIT(1);
1596 else
1597 pstat->uapsd_vo = 0;
1598
1599 if (pstat->qos_info & BIT(1))
1600 pstat->uapsd_vi = BIT(0)|BIT(1);
1601 else
1602 pstat->uapsd_vi = 0;
1603
1604 if (pstat->qos_info & BIT(2))
1605 pstat->uapsd_bk = BIT(0)|BIT(1);
1606 else
1607 pstat->uapsd_bk = 0;
1608
1609 if (pstat->qos_info & BIT(3))
1610 pstat->uapsd_be = BIT(0)|BIT(1);
1611 else
1612 pstat->uapsd_be = 0;
1613
1614 break;
1615 }
1616 } else {
1617 break;
1618 }
1619 p = p + p[1] + 2;
1620 }
1621 }
1622
1623 /* save HT capabilities in the sta object */
1624 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1625 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
1626
1627 if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
1628 pstat->flags |= WLAN_STA_HT;
1629
1630 pstat->flags |= WLAN_STA_WME;
1631
1632 memcpy(&pstat->htpriv.ht_cap, p + 2,
1633 sizeof(struct ieee80211_ht_cap));
1634 } else
1635 pstat->flags &= ~WLAN_STA_HT;
1636
1637 if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
1638 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1639 goto OnAssocReq23aFail;
1640 }
1641
1642 if (pstat->flags & WLAN_STA_HT &&
1643 (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
1644 pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
1645 DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
1646 pstat->hwaddr);
1647
1648 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1649 /* goto OnAssocReq23aFail; */
1650 }
1651
1652 pstat->flags |= WLAN_STA_NONERP;
1653 for (i = 0; i < pstat->bssratelen; i++) {
1654 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1655 pstat->flags &= ~WLAN_STA_NONERP;
1656 break;
1657 }
1658 }
1659
1660 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1661 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1662 else
1663 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1664
1665 if (status != WLAN_STATUS_SUCCESS)
1666 goto OnAssocReq23aFail;
1667
1668 /* TODO: identify_proprietary_vendor_ie(); */
1669 /* Realtek proprietary IE */
1670 /* identify if this is Broadcom sta */
1671 /* identify if this is ralink sta */
1672 /* Customer proprietary IE */
1673
1674 /* get a unique AID */
1675 if (pstat->aid > 0) {
1676 DBG_8723A(" old AID %d\n", pstat->aid);
1677 } else {
1678 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1679 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1680 break;
1681
1682 if (pstat->aid > NUM_STA)
1683 pstat->aid = NUM_STA;
1684 if (pstat->aid > pstapriv->max_num_sta) {
1685
1686 pstat->aid = 0;
1687
1688 DBG_8723A(" no room for more AIDs\n");
1689
1690 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1691
1692 goto OnAssocReq23aFail;
1693 } else {
1694 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1695 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1696 }
1697 }
1698
1699 pstat->state &= ~WIFI_FW_ASSOC_STATE;
1700 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1701
1702 spin_lock_bh(&pstapriv->auth_list_lock);
1703 if (!list_empty(&pstat->auth_list)) {
1704 list_del_init(&pstat->auth_list);
1705 pstapriv->auth_list_cnt--;
1706 }
1707 spin_unlock_bh(&pstapriv->auth_list_lock);
1708
1709 spin_lock_bh(&pstapriv->asoc_list_lock);
1710 if (list_empty(&pstat->asoc_list)) {
1711 pstat->expire_to = pstapriv->expire_to;
1712 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1713 pstapriv->asoc_list_cnt++;
1714 }
1715 spin_unlock_bh(&pstapriv->asoc_list_lock);
1716
1717 /* now the station is qualified to join our BSS... */
1718 if (pstat->state & WIFI_FW_ASSOC_SUCCESS &&
1719 status == WLAN_STATUS_SUCCESS) {
1720 /* 1 bss_cap_update & sta_info_update23a */
1721 bss_cap_update_on_sta_join23a(padapter, pstat);
1722 sta_info_update23a(padapter, pstat);
1723
1724 /* issue assoc rsp before notify station join event. */
1725 if (ieee80211_is_assoc_req(mgmt->frame_control))
1726 issue_assocrsp(padapter, status, pstat,
1727 IEEE80211_STYPE_ASSOC_RESP);
1728 else
1729 issue_assocrsp(padapter, status, pstat,
1730 IEEE80211_STYPE_REASSOC_RESP);
1731
1732 /* 2 - report to upper layer */
1733 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1734 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1735
1736 /* 3-(1) report sta add event */
1737 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1738 }
1739
1740 return _SUCCESS;
1741
1742 asoc_class2_error:
1743
1744 issue_deauth23a(padapter, mgmt->sa, status);
1745 return _FAIL;
1746
1747 OnAssocReq23aFail:
1748
1749 pstat->aid = 0;
1750 if (ieee80211_is_assoc_req(mgmt->frame_control))
1751 issue_assocrsp(padapter, status, pstat,
1752 IEEE80211_STYPE_ASSOC_RESP);
1753 else
1754 issue_assocrsp(padapter, status, pstat,
1755 IEEE80211_STYPE_REASSOC_RESP);
1756
1757 #endif /* CONFIG_8723AU_AP_MODE */
1758
1759 return _FAIL;
1760 }
1761
1762 static int
1763 OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1764 {
1765 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1766 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1767 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1768 struct sk_buff *skb = precv_frame->pkt;
1769 struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
1770 int res;
1771 unsigned short status;
1772 const u8 *p, *pie;
1773 u8 *pframe = skb->data;
1774 int pkt_len = skb->len;
1775 int pielen;
1776
1777 DBG_8723A("%s\n", __func__);
1778
1779 /* check A1 matches or not */
1780 if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
1781 return _SUCCESS;
1782
1783 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1784 return _SUCCESS;
1785
1786 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1787 return _SUCCESS;
1788
1789 del_timer_sync(&pmlmeext->link_timer);
1790
1791 /* status */
1792 status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
1793 if (status > 0) {
1794 DBG_8723A("assoc reject, status code: %d\n", status);
1795 pmlmeinfo->state = MSR_NOLINK;
1796 res = -4;
1797 goto report_assoc_result;
1798 }
1799
1800 /* get capabilities */
1801 pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
1802
1803 /* set slot time */
1804 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1805
1806 /* AID */
1807 res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
1808
1809 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1810 pielen = pkt_len -
1811 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1812
1813 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
1814 pmgmt->u.assoc_resp.variable, pielen);
1815 if (p && p[1])
1816 HT_caps_handler23a(padapter, p);
1817
1818 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
1819 pmgmt->u.assoc_resp.variable, pielen);
1820 if (p && p[1])
1821 HT_info_handler23a(padapter, p);
1822
1823 p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
1824 pmgmt->u.assoc_resp.variable, pielen);
1825 if (p && p[1])
1826 ERP_IE_handler23a(padapter, p);
1827
1828 pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
1829 while (true) {
1830 p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
1831 WLAN_OUI_TYPE_MICROSOFT_WMM,
1832 pie, pframe + pkt_len - pie);
1833 if (!p)
1834 break;
1835
1836 pie = p + p[1] + 2;
1837 /* if this IE is too short, try the next */
1838 if (p[1] <= 4)
1839 continue;
1840 /* if this IE is WMM params, we found what we wanted */
1841 if (p[6] == 1)
1842 break;
1843 }
1844
1845 if (p && p[1])
1846 WMM_param_handler23a(padapter, p);
1847
1848 pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
1849 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1850
1851 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1852 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1853
1854 report_assoc_result:
1855 pmlmepriv->assoc_rsp_len = 0;
1856 if (res > 0) {
1857 kfree(pmlmepriv->assoc_rsp);
1858 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1859 if (pmlmepriv->assoc_rsp) {
1860 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1861 pmlmepriv->assoc_rsp_len = pkt_len;
1862 }
1863 } else
1864 kfree(pmlmepriv->assoc_rsp);
1865
1866 report_join_res23a(padapter, res);
1867
1868 return _SUCCESS;
1869 }
1870
1871 static int
1872 OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1873 {
1874 unsigned short reason;
1875 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1876 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1877 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1878 struct sk_buff *skb = precv_frame->pkt;
1879 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1880
1881 if (!ether_addr_equal(mgmt->bssid,
1882 get_my_bssid23a(&pmlmeinfo->network)))
1883 return _SUCCESS;
1884
1885 reason = le16_to_cpu(mgmt->u.deauth.reason_code);
1886
1887 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1888
1889 #ifdef CONFIG_8723AU_AP_MODE
1890 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1891 struct sta_info *psta;
1892 struct sta_priv *pstapriv = &padapter->stapriv;
1893
1894 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1895 "sta:%pM\n", reason, mgmt->sa);
1896
1897 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1898 if (psta) {
1899 u8 updated = 0;
1900
1901 spin_lock_bh(&pstapriv->asoc_list_lock);
1902 if (!list_empty(&psta->asoc_list)) {
1903 list_del_init(&psta->asoc_list);
1904 pstapriv->asoc_list_cnt--;
1905 updated = ap_free_sta23a(padapter, psta,
1906 false, reason);
1907 }
1908 spin_unlock_bh(&pstapriv->asoc_list_lock);
1909
1910 associated_clients_update23a(padapter, updated);
1911 }
1912
1913 return _SUCCESS;
1914 } else
1915 #endif
1916 {
1917 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1918 "sta:%pM\n", reason, mgmt->bssid);
1919
1920 receive_disconnect23a(padapter, mgmt->bssid, reason);
1921 }
1922 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1923
1924 return _SUCCESS;
1925 }
1926
1927 static int
1928 OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1929 {
1930 unsigned short reason;
1931 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1932 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1933 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1934 struct sk_buff *skb = precv_frame->pkt;
1935 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
1936
1937 if (!ether_addr_equal(mgmt->bssid,
1938 get_my_bssid23a(&pmlmeinfo->network)))
1939 return _SUCCESS;
1940
1941 reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
1942
1943 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1944
1945 #ifdef CONFIG_8723AU_AP_MODE
1946 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1947 struct sta_info *psta;
1948 struct sta_priv *pstapriv = &padapter->stapriv;
1949
1950 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1951 " sta:%pM\n", reason, mgmt->sa);
1952
1953 psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
1954 if (psta) {
1955 u8 updated = 0;
1956
1957 spin_lock_bh(&pstapriv->asoc_list_lock);
1958 if (!list_empty(&psta->asoc_list)) {
1959 list_del_init(&psta->asoc_list);
1960 pstapriv->asoc_list_cnt--;
1961 updated = ap_free_sta23a(padapter, psta,
1962 false, reason);
1963 }
1964 spin_unlock_bh(&pstapriv->asoc_list_lock);
1965
1966 associated_clients_update23a(padapter, updated);
1967 }
1968
1969 return _SUCCESS;
1970 } else
1971 #endif
1972 {
1973 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
1974 "code(%d) sta:%pM\n", reason, mgmt->bssid);
1975
1976 receive_disconnect23a(padapter, mgmt->bssid, reason);
1977 }
1978 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1979 return _SUCCESS;
1980 }
1981
1982 static int
1983 OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1984 {
1985 DBG_8723A("%s\n", __func__);
1986 return _SUCCESS;
1987 }
1988
1989 static int
1990 on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1991 {
1992 return _FAIL;
1993 }
1994
1995 static int
1996 OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1997 {
1998 return _SUCCESS;
1999 }
2000
2001 static int
2002 OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2003 {
2004 return _SUCCESS;
2005 }
2006
2007 static int OnAction23a_back23a(struct rtw_adapter *padapter,
2008 struct recv_frame *precv_frame)
2009 {
2010 u8 *addr;
2011 struct sta_info *psta = NULL;
2012 struct recv_reorder_ctrl *preorder_ctrl;
2013 unsigned char category, action;
2014 unsigned short tid, status, capab, params, reason_code = 0;
2015 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2016 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2017 struct sk_buff *skb = precv_frame->pkt;
2018 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2019 struct sta_priv *pstapriv = &padapter->stapriv;
2020
2021 /* check RA matches or not */
2022 if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
2023 return _SUCCESS;
2024
2025 DBG_8723A("%s\n", __func__);
2026
2027 if ((pmlmeinfo->state&0x03) != MSR_AP)
2028 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2029 return _SUCCESS;
2030
2031 addr = mgmt->sa;
2032 psta = rtw_get_stainfo23a(pstapriv, addr);
2033
2034 if (!psta)
2035 return _SUCCESS;
2036
2037 category = mgmt->u.action.category;
2038 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2039 if (!pmlmeinfo->HT_enable)
2040 return _SUCCESS;
2041 /* action_code is located in the same place for all
2042 action events, so pick any */
2043 action = mgmt->u.action.u.wme_action.action_code;
2044 DBG_8723A("%s, action =%d\n", __func__, action);
2045 switch (action) {
2046 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2047 memcpy(&pmlmeinfo->ADDBA_req,
2048 &mgmt->u.action.u.addba_req.dialog_token,
2049 sizeof(struct ADDBA_request));
2050 process_addba_req23a(padapter,
2051 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2052 if (pmlmeinfo->bAcceptAddbaReq == true)
2053 issue_action_BA23a(padapter, addr,
2054 WLAN_ACTION_ADDBA_RESP, 0);
2055 else {
2056 /* reject ADDBA Req */
2057 issue_action_BA23a(padapter, addr,
2058 WLAN_ACTION_ADDBA_RESP, 37);
2059 }
2060 break;
2061 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2062 status = get_unaligned_le16(
2063 &mgmt->u.action.u.addba_resp.status);
2064 capab = get_unaligned_le16(
2065 &mgmt->u.action.u.addba_resp.capab);
2066 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
2067 if (status == 0) { /* successful */
2068 DBG_8723A("agg_enable for TID =%d\n", tid);
2069 psta->htpriv.agg_enable_bitmap |= BIT(tid);
2070 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2071 } else
2072 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2073 break;
2074
2075 case WLAN_ACTION_DELBA: /* DELBA */
2076 params = get_unaligned_le16(
2077 &mgmt->u.action.u.delba.params);
2078 tid = params >> 12;
2079
2080 if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
2081 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2082 preorder_ctrl->enable = false;
2083 preorder_ctrl->indicate_seq = 0xffff;
2084 } else {
2085 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
2086 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
2087 }
2088 reason_code = get_unaligned_le16(
2089 &mgmt->u.action.u.delba.reason_code);
2090 /* todo: how to notify the host while receiving
2091 DELETE BA */
2092 break;
2093 default:
2094 break;
2095 }
2096 }
2097 return _SUCCESS;
2098 }
2099
2100 static int on_action_public23a(struct rtw_adapter *padapter,
2101 struct recv_frame *precv_frame)
2102 {
2103 struct sk_buff *skb = precv_frame->pkt;
2104 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2105 u8 *pframe = skb->data;
2106 int freq, channel;
2107
2108 /* check RA matches or not */
2109 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2110 return _FAIL;
2111
2112 channel = rtw_get_oper_ch23a(padapter);
2113
2114 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2115 freq = ieee80211_channel_to_frequency(channel,
2116 NL80211_BAND_2GHZ);
2117 else
2118 freq = ieee80211_channel_to_frequency(channel,
2119 NL80211_BAND_5GHZ);
2120
2121 if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
2122 skb->len, 0))
2123 return _SUCCESS;
2124
2125 return _FAIL;
2126 }
2127
2128 static int
2129 OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2130 {
2131 return _SUCCESS;
2132 }
2133
2134 static int
2135 OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2136 {
2137 return _SUCCESS;
2138 }
2139
2140 static int
2141 OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2142 {
2143 return _SUCCESS;
2144 }
2145
2146 static int
2147 OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2148 {
2149 int i;
2150 u8 category;
2151 struct action_handler *ptable;
2152 struct sk_buff *skb = precv_frame->pkt;
2153 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
2154
2155 category = mgmt->u.action.category;
2156
2157 for (i = 0; i < ARRAY_SIZE(OnAction23a_tbl); i++) {
2158 ptable = &OnAction23a_tbl[i];
2159
2160 if (category == ptable->num)
2161 ptable->func(padapter, precv_frame);
2162 }
2163
2164 return _SUCCESS;
2165 }
2166
2167 static int DoReserved23a(struct rtw_adapter *padapter,
2168 struct recv_frame *precv_frame)
2169 {
2170 return _SUCCESS;
2171 }
2172
2173 struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
2174 {
2175 struct xmit_frame *pmgntframe;
2176 struct xmit_buf *pxmitbuf;
2177
2178 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
2179
2180 if (!pmgntframe) {
2181 DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
2182 pxmitpriv->adapter->pnetdev->name);
2183 goto exit;
2184 }
2185
2186 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
2187 if (!pxmitbuf) {
2188 DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
2189 pxmitpriv->adapter->pnetdev->name);
2190 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
2191 pmgntframe = NULL;
2192 goto exit;
2193 }
2194
2195 pmgntframe->frame_tag = MGNT_FRAMETAG;
2196 pmgntframe->pxmitbuf = pxmitbuf;
2197 pmgntframe->buf_addr = pxmitbuf->pbuf;
2198 pxmitbuf->priv_data = pmgntframe;
2199
2200 exit:
2201 return pmgntframe;
2202 }
2203
2204 /****************************************************************************
2205
2206 Following are some TX functions for WiFi MLME
2207
2208 *****************************************************************************/
2209
2210 void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
2211 {
2212 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2213
2214 pmlmeext->tx_rate = rate;
2215 DBG_8723A("%s(): rate = %x\n", __func__, rate);
2216 }
2217
2218 void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
2219 struct pkt_attrib *pattrib)
2220 {
2221 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2222
2223 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
2224
2225 pattrib->hdrlen = 24;
2226 pattrib->nr_frags = 1;
2227 pattrib->priority = 7;
2228 pattrib->mac_id = 0;
2229 pattrib->qsel = 0x12;
2230
2231 pattrib->pktlen = 0;
2232
2233 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
2234 pattrib->raid = 6;/* b mode */
2235 else
2236 pattrib->raid = 5;/* a/g mode */
2237
2238 pattrib->encrypt = 0;
2239 pattrib->bswenc = false;
2240
2241 pattrib->qos_en = false;
2242 pattrib->ht_en = false;
2243 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
2244 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2245 pattrib->sgi = false;
2246
2247 pattrib->seqnum = pmlmeext->mgnt_seq;
2248
2249 pattrib->retry_ctrl = true;
2250 }
2251
2252 void dump_mgntframe23a(struct rtw_adapter *padapter,
2253 struct xmit_frame *pmgntframe)
2254 {
2255 if (padapter->bSurpriseRemoved == true ||
2256 padapter->bDriverStopped == true)
2257 return;
2258
2259 rtl8723au_mgnt_xmit(padapter, pmgntframe);
2260 }
2261
2262 int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
2263 struct xmit_frame *pmgntframe, int timeout_ms)
2264 {
2265 int ret = _FAIL;
2266 unsigned long irqL;
2267 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2268 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2269 struct submit_ctx sctx;
2270
2271 if (padapter->bSurpriseRemoved == true ||
2272 padapter->bDriverStopped == true)
2273 return ret;
2274
2275 rtw_sctx_init23a(&sctx, timeout_ms);
2276 pxmitbuf->sctx = &sctx;
2277
2278 ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
2279
2280 if (ret == _SUCCESS)
2281 ret = rtw_sctx_wait23a(&sctx);
2282
2283 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2284 pxmitbuf->sctx = NULL;
2285 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2286
2287 return ret;
2288 }
2289
2290 int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
2291 struct xmit_frame *pmgntframe)
2292 {
2293 int ret = _FAIL;
2294 u32 timeout_ms = 500;/* 500ms */
2295 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2296
2297 if (padapter->bSurpriseRemoved == true ||
2298 padapter->bDriverStopped == true)
2299 return _FAIL;
2300
2301 mutex_lock(&pxmitpriv->ack_tx_mutex);
2302 pxmitpriv->ack_tx = true;
2303
2304 pmgntframe->ack_report = 1;
2305 if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2306 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
2307
2308 pxmitpriv->ack_tx = false;
2309 mutex_unlock(&pxmitpriv->ack_tx_mutex);
2310
2311 return ret;
2312 }
2313
2314 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2315 {
2316 u8 *ssid_ie;
2317 int ssid_len_ori;
2318 int len_diff = 0;
2319 u8 *next_ie;
2320 u32 remain_len;
2321
2322 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
2323
2324 /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
2325 __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2326
2327 if (ssid_ie && ssid_len_ori > 0) {
2328 switch (hidden_ssid_mode) {
2329 case 1:
2330 next_ie = ssid_ie + 2 + ssid_len_ori;
2331 remain_len = ies_len -(next_ie-ies);
2332
2333 ssid_ie[1] = 0;
2334 memcpy(ssid_ie+2, next_ie, remain_len);
2335 len_diff -= ssid_len_ori;
2336
2337 break;
2338 case 2:
2339 memset(&ssid_ie[2], 0, ssid_len_ori);
2340 break;
2341 default:
2342 break;
2343 }
2344 }
2345
2346 return len_diff;
2347 }
2348
2349 void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
2350 {
2351 struct xmit_frame *pmgntframe;
2352 struct pkt_attrib *pattrib;
2353 unsigned char *pframe;
2354 struct ieee80211_mgmt *mgmt;
2355 unsigned int rate_len;
2356 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2357 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2358 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2359 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2360 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2361 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2362 const u8 *wps_ie;
2363 u8 sr = 0;
2364 int len_diff;
2365
2366 /* DBG_8723A("%s\n", __func__); */
2367
2368 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2369 if (!pmgntframe) {
2370 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2371 return;
2372 }
2373 #ifdef CONFIG_8723AU_AP_MODE
2374 spin_lock_bh(&pmlmepriv->bcn_update_lock);
2375 #endif
2376
2377 /* update attribute */
2378 pattrib = &pmgntframe->attrib;
2379 update_mgntframe_attrib23a(padapter, pattrib);
2380 pattrib->qsel = 0x10;
2381
2382 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2383
2384 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2385 mgmt = (struct ieee80211_mgmt *)pframe;
2386
2387 mgmt->frame_control =
2388 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
2389 mgmt->seq_ctrl = 0;
2390
2391 ether_addr_copy(mgmt->da, bc_addr);
2392 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2393 ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
2394
2395 /* timestamp will be inserted by hardware */
2396
2397 put_unaligned_le16(cur_network->beacon_interval,
2398 &mgmt->u.beacon.beacon_int);
2399
2400 put_unaligned_le16(cur_network->capability,
2401 &mgmt->u.beacon.capab_info);
2402
2403 pframe = mgmt->u.beacon.variable;
2404 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
2405
2406 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2407 u8 *iebuf;
2408 int buflen;
2409 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
2410 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2411 len_diff = update_hidden_ssid(pframe, cur_network->IELength,
2412 pmlmeinfo->hidden_ssid_mode);
2413 pframe += (cur_network->IELength+len_diff);
2414 pattrib->pktlen += (cur_network->IELength+len_diff);
2415
2416 iebuf = mgmt->u.beacon.variable;
2417 buflen = pattrib->pktlen -
2418 offsetof(struct ieee80211_mgmt, u.beacon.variable);
2419 wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2420 WLAN_OUI_TYPE_MICROSOFT_WPS,
2421 iebuf, buflen);
2422
2423 if (wps_ie && wps_ie[1] > 0) {
2424 rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
2425 WPS_ATTR_SELECTED_REGISTRAR,
2426 (u8 *)&sr);
2427 }
2428 if (sr != 0)
2429 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2430 else
2431 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2432
2433 goto _issue_bcn;
2434 }
2435
2436 /* SSID */
2437 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2438 cur_network->Ssid.ssid_len,
2439 cur_network->Ssid.ssid, &pattrib->pktlen);
2440
2441 /* supported rates... */
2442 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2443 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2444 ((rate_len > 8)? 8: rate_len),
2445 cur_network->SupportedRates, &pattrib->pktlen);
2446
2447 /* DS parameter set */
2448 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
2449 &cur_network->DSConfig, &pattrib->pktlen);
2450
2451 /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
2452 {
2453 u8 erpinfo = 0;
2454 u32 ATIMWindow;
2455 /* IBSS Parameter Set... */
2456 /* ATIMWindow = cur->ATIMWindow; */
2457 ATIMWindow = 0;
2458 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2459 (unsigned char *)&ATIMWindow,
2460 &pattrib->pktlen);
2461
2462 /* ERP IE */
2463 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2464 &erpinfo, &pattrib->pktlen);
2465 }
2466
2467 /* EXTERNDED SUPPORTED RATE */
2468 if (rate_len > 8)
2469 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2470 rate_len - 8,
2471 cur_network->SupportedRates + 8,
2472 &pattrib->pktlen);
2473
2474 /* todo:HT for adhoc */
2475
2476 _issue_bcn:
2477
2478 #ifdef CONFIG_8723AU_AP_MODE
2479 pmlmepriv->update_bcn = false;
2480
2481 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2482 #endif
2483
2484 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2485 DBG_8723A("beacon frame too large\n");
2486 return;
2487 }
2488
2489 pattrib->last_txcmdsz = pattrib->pktlen;
2490
2491 /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2492 if (timeout_ms > 0)
2493 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
2494 else
2495 dump_mgntframe23a(padapter, pmgntframe);
2496 }
2497
2498 static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da)
2499 {
2500 struct xmit_frame *pmgntframe;
2501 struct pkt_attrib *pattrib;
2502 unsigned char *pframe;
2503 struct ieee80211_mgmt *mgmt;
2504 unsigned char *mac, *bssid;
2505 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2506 #ifdef CONFIG_8723AU_AP_MODE
2507 const u8 *pwps_ie;
2508 u8 *ssid_ie;
2509 int ssid_ielen;
2510 int ssid_ielen_diff;
2511 u8 buf[MAX_IE_SZ];
2512 #endif
2513 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2514 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2515 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
2516 unsigned int rate_len;
2517
2518 /* DBG_8723A("%s\n", __func__); */
2519
2520 if (cur_network->IELength > MAX_IE_SZ)
2521 return;
2522
2523 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2524 if (!pmgntframe) {
2525 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
2526 return;
2527 }
2528
2529 /* update attribute */
2530 pattrib = &pmgntframe->attrib;
2531 update_mgntframe_attrib23a(padapter, pattrib);
2532
2533 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2534
2535 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
2536 mgmt = (struct ieee80211_mgmt *)pframe;
2537
2538 mac = myid(&padapter->eeprompriv);
2539 bssid = cur_network->MacAddress;
2540
2541 mgmt->frame_control =
2542 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
2543
2544 ether_addr_copy(mgmt->da, da);
2545 ether_addr_copy(mgmt->sa, mac);
2546 ether_addr_copy(mgmt->bssid, bssid);
2547
2548 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2549 pmlmeext->mgnt_seq++;
2550
2551 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2552
2553 /* timestamp will be inserted by hardware */
2554 put_unaligned_le16(cur_network->beacon_interval,
2555 &mgmt->u.probe_resp.beacon_int);
2556
2557 put_unaligned_le16(cur_network->capability,
2558 &mgmt->u.probe_resp.capab_info);
2559
2560 pframe = mgmt->u.probe_resp.variable;
2561 pattrib->pktlen =
2562 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
2563
2564 /* below for ad-hoc mode */
2565
2566 #ifdef CONFIG_8723AU_AP_MODE
2567 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
2568 pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
2569 WLAN_OUI_TYPE_MICROSOFT_WPS,
2570 cur_network->IEs,
2571 cur_network->IELength);
2572
2573 memcpy(pframe, cur_network->IEs, cur_network->IELength);
2574 pframe += cur_network->IELength;
2575 pattrib->pktlen += cur_network->IELength;
2576
2577 /* retrieve SSID IE from cur_network->Ssid */
2578
2579 ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
2580 WLAN_EID_SSID, &ssid_ielen,
2581 pframe - mgmt->u.probe_resp.variable);
2582
2583 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
2584
2585 if (ssid_ie && cur_network->Ssid.ssid_len) {
2586 uint remainder_ielen;
2587 u8 *remainder_ie;
2588
2589 remainder_ie = ssid_ie + 2;
2590
2591 remainder_ielen = pframe - remainder_ie;
2592
2593 DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
2594 "remainder_ielen > MAX_IE_SZ\n",
2595 __func__, padapter->pnetdev->name);
2596 if (remainder_ielen > MAX_IE_SZ)
2597 remainder_ielen = MAX_IE_SZ;
2598
2599 memcpy(buf, remainder_ie, remainder_ielen);
2600 memcpy(remainder_ie + ssid_ielen_diff, buf,
2601 remainder_ielen);
2602 *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
2603 memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
2604 cur_network->Ssid.ssid_len);
2605
2606 pframe += ssid_ielen_diff;
2607 pattrib->pktlen += ssid_ielen_diff;
2608 }
2609 } else
2610 #endif
2611 {
2612 /* SSID */
2613 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
2614 cur_network->Ssid.ssid_len,
2615 cur_network->Ssid.ssid,
2616 &pattrib->pktlen);
2617
2618 /* supported rates... */
2619 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
2620 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2621 ((rate_len > 8)? 8: rate_len),
2622 cur_network->SupportedRates,
2623 &pattrib->pktlen);
2624
2625 /* DS parameter set */
2626 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
2627 (unsigned char *)&cur_network->DSConfig,
2628 &pattrib->pktlen);
2629
2630 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
2631 u8 erpinfo = 0;
2632 u32 ATIMWindow;
2633 /* IBSS Parameter Set... */
2634 /* ATIMWindow = cur->ATIMWindow; */
2635 ATIMWindow = 0;
2636 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
2637 (unsigned char *)&ATIMWindow,
2638 &pattrib->pktlen);
2639
2640 /* ERP IE */
2641 pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
2642 &erpinfo, &pattrib->pktlen);
2643 }
2644
2645 /* EXTERNDED SUPPORTED RATE */
2646 if (rate_len > 8)
2647 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2648 rate_len - 8,
2649 cur_network->SupportedRates + 8,
2650 &pattrib->pktlen);
2651
2652 /* todo:HT for adhoc */
2653 }
2654
2655 pattrib->last_txcmdsz = pattrib->pktlen;
2656
2657 dump_mgntframe23a(padapter, pmgntframe);
2658 }
2659
2660 static int _issue_probereq(struct rtw_adapter *padapter,
2661 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
2662 {
2663 int ret = _FAIL;
2664 struct xmit_frame *pmgntframe;
2665 struct pkt_attrib *pattrib;
2666 unsigned char *pframe;
2667 struct ieee80211_hdr *pwlanhdr;
2668 unsigned char *mac;
2669 unsigned char bssrate[NumRates];
2670 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2671 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2672 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2673 int bssrate_len = 0;
2674 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2675
2676 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2677 "+%s\n", __func__);
2678
2679 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2680 if (!pmgntframe)
2681 goto exit;
2682
2683 /* update attribute */
2684 pattrib = &pmgntframe->attrib;
2685 update_mgntframe_attrib23a(padapter, pattrib);
2686
2687 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2688
2689 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2690 pwlanhdr = (struct ieee80211_hdr *)pframe;
2691
2692 mac = myid(&padapter->eeprompriv);
2693
2694 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2695 IEEE80211_STYPE_PROBE_REQ);
2696
2697 if (da) {
2698 /* unicast probe request frame */
2699 ether_addr_copy(pwlanhdr->addr1, da);
2700 ether_addr_copy(pwlanhdr->addr3, da);
2701 } else {
2702 /* broadcast probe request frame */
2703 ether_addr_copy(pwlanhdr->addr1, bc_addr);
2704 ether_addr_copy(pwlanhdr->addr3, bc_addr);
2705 }
2706
2707 ether_addr_copy(pwlanhdr->addr2, mac);
2708
2709 pwlanhdr->seq_ctrl =
2710 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2711
2712 pmlmeext->mgnt_seq++;
2713
2714 pframe += sizeof (struct ieee80211_hdr_3addr);
2715 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
2716
2717 if (pssid)
2718 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
2719 pssid->ssid, &pattrib->pktlen);
2720 else
2721 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
2722 &pattrib->pktlen);
2723
2724 get_rate_set23a(padapter, bssrate, &bssrate_len);
2725
2726 if (bssrate_len > 8) {
2727 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
2728 bssrate, &pattrib->pktlen);
2729 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
2730 (bssrate_len - 8), (bssrate + 8),
2731 &pattrib->pktlen);
2732 } else {
2733 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
2734 bssrate_len, bssrate, &pattrib->pktlen);
2735 }
2736
2737 /* add wps_ie for wps2.0 */
2738 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
2739 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
2740 pmlmepriv->wps_probe_req_ie_len);
2741 pframe += pmlmepriv->wps_probe_req_ie_len;
2742 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2743 }
2744
2745 pattrib->last_txcmdsz = pattrib->pktlen;
2746
2747 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2748 "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
2749
2750 if (wait_ack) {
2751 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
2752 } else {
2753 dump_mgntframe23a(padapter, pmgntframe);
2754 ret = _SUCCESS;
2755 }
2756
2757 exit:
2758 return ret;
2759 }
2760
2761 static inline void issue_probereq(struct rtw_adapter *padapter,
2762 struct cfg80211_ssid *pssid, u8 *da)
2763 {
2764 _issue_probereq(padapter, pssid, da, false);
2765 }
2766
2767 static int issue_probereq_ex(struct rtw_adapter *padapter,
2768 struct cfg80211_ssid *pssid, u8 *da,
2769 int try_cnt, int wait_ms)
2770 {
2771 int ret;
2772 int i = 0;
2773 unsigned long start = jiffies;
2774
2775 do {
2776 ret = _issue_probereq(padapter, pssid, da,
2777 wait_ms > 0 ? true : false);
2778
2779 i++;
2780
2781 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2782 break;
2783
2784 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2785 msleep(wait_ms);
2786
2787 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2788
2789 if (ret != _FAIL) {
2790 ret = _SUCCESS;
2791 goto exit;
2792 }
2793
2794 if (try_cnt && wait_ms) {
2795 if (da)
2796 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
2797 __func__, padapter->pnetdev->name,
2798 da, rtw_get_oper_ch23a(padapter),
2799 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2800 jiffies_to_msecs(jiffies - start));
2801 else
2802 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
2803 __func__, padapter->pnetdev->name,
2804 rtw_get_oper_ch23a(padapter),
2805 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
2806 jiffies_to_msecs(jiffies - start));
2807 }
2808 exit:
2809 return ret;
2810 }
2811
2812 /* if psta == NULL, indiate we are station(client) now... */
2813 static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
2814 unsigned short status)
2815 {
2816 struct xmit_frame *pmgntframe;
2817 struct pkt_attrib *pattrib;
2818 unsigned char *pframe;
2819 struct ieee80211_mgmt *mgmt;
2820 unsigned int val32;
2821 u16 auth_algo;
2822 int use_shared_key = 0;
2823 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2824 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2825 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2826
2827 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2828 if (!pmgntframe)
2829 return;
2830
2831 /* update attribute */
2832 pattrib = &pmgntframe->attrib;
2833 update_mgntframe_attrib23a(padapter, pattrib);
2834
2835 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2836
2837 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2838 mgmt = (struct ieee80211_mgmt *)pframe;
2839
2840 mgmt->frame_control =
2841 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
2842 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2843 pmlmeext->mgnt_seq++;
2844
2845 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
2846
2847 if (psta) { /* for AP mode */
2848 #ifdef CONFIG_8723AU_AP_MODE
2849 unsigned short val16;
2850
2851 ether_addr_copy(mgmt->da, psta->hwaddr);
2852 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2853 ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
2854
2855 /* setting auth algo number */
2856 val16 = (u16)psta->authalg;
2857
2858 if (status != WLAN_STATUS_SUCCESS)
2859 val16 = 0;
2860
2861 if (val16)
2862 use_shared_key = 1;
2863
2864 mgmt->u.auth.auth_alg = cpu_to_le16(val16);
2865
2866 /* setting auth seq number */
2867 mgmt->u.auth.auth_transaction =
2868 cpu_to_le16((u16)psta->auth_seq);
2869
2870 /* setting status code... */
2871 mgmt->u.auth.status_code = cpu_to_le16(status);
2872
2873 pframe = mgmt->u.auth.variable;
2874 /* added challenging text... */
2875 if ((psta->auth_seq == 2) &&
2876 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2877 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2878 psta->chg_txt, &pattrib->pktlen);
2879 #endif
2880 } else {
2881 struct ieee80211_mgmt *iv_mgmt;
2882
2883 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
2884 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2885 ether_addr_copy(mgmt->bssid,
2886 get_my_bssid23a(&pmlmeinfo->network));
2887
2888 /* setting auth algo number */
2889 /* 0:OPEN System, 1:Shared key */
2890 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
2891 use_shared_key = 1;
2892 auth_algo = WLAN_AUTH_SHARED_KEY;
2893 } else
2894 auth_algo = WLAN_AUTH_OPEN;
2895
2896 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
2897 (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
2898 pmlmeinfo->auth_seq); */
2899
2900 /* setting IV for auth seq #3 */
2901 if ((pmlmeinfo->auth_seq == 3) &&
2902 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2903 (use_shared_key == 1)) {
2904 u32 *piv = (u32 *)&mgmt->u.auth;
2905
2906 iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
2907 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
2908 pmlmeinfo->iv, pmlmeinfo->key_index); */
2909 val32 = (pmlmeinfo->iv & 0x3fffffff) |
2910 (pmlmeinfo->key_index << 30);
2911 pmlmeinfo->iv++;
2912 put_unaligned_le32(val32, piv);
2913
2914 pattrib->pktlen += 4;
2915
2916 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
2917 } else
2918 iv_mgmt = mgmt;
2919
2920 iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
2921
2922 /* setting auth seq number */
2923 iv_mgmt->u.auth.auth_transaction =
2924 cpu_to_le16(pmlmeinfo->auth_seq);
2925
2926 /* setting status code... */
2927 iv_mgmt->u.auth.status_code = cpu_to_le16(status);
2928
2929 pframe = iv_mgmt->u.auth.variable;
2930
2931 /* then checking to see if sending challenging text... */
2932 if ((pmlmeinfo->auth_seq == 3) &&
2933 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
2934 (use_shared_key == 1)) {
2935 pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
2936 pmlmeinfo->chg_txt,
2937 &pattrib->pktlen);
2938
2939 mgmt->frame_control |=
2940 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
2941
2942 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2943
2944 pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
2945
2946 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
2947
2948 pattrib->pktlen += pattrib->icv_len;
2949 }
2950 }
2951
2952 pattrib->last_txcmdsz = pattrib->pktlen;
2953
2954 rtw_wep_encrypt23a(padapter, pmgntframe);
2955 DBG_8723A("%s\n", __func__);
2956 dump_mgntframe23a(padapter, pmgntframe);
2957 }
2958
2959 #ifdef CONFIG_8723AU_AP_MODE
2960 static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
2961 struct sta_info *pstat, u16 pkt_type)
2962 {
2963 struct xmit_frame *pmgntframe;
2964 struct ieee80211_mgmt *mgmt;
2965 struct pkt_attrib *pattrib;
2966 unsigned char *pframe;
2967 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2968 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2969 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2970 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2971 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
2972 const u8 *p;
2973 u8 *ie = pnetwork->IEs;
2974
2975 DBG_8723A("%s\n", __func__);
2976
2977 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2978 if (!pmgntframe)
2979 return;
2980
2981 /* update attribute */
2982 pattrib = &pmgntframe->attrib;
2983 update_mgntframe_attrib23a(padapter, pattrib);
2984
2985 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2986
2987 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2988 mgmt = (struct ieee80211_mgmt *)pframe;
2989
2990 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
2991
2992 ether_addr_copy(mgmt->da, pstat->hwaddr);
2993 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
2994 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
2995
2996 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
2997
2998 pmlmeext->mgnt_seq++;
2999
3000 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3001 pattrib->pktlen =
3002 offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
3003
3004 mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
3005 mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
3006 mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3007
3008 pframe = mgmt->u.assoc_resp.variable;
3009
3010 if (pstat->bssratelen <= 8) {
3011 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3012 pstat->bssratelen, pstat->bssrateset,
3013 &pattrib->pktlen);
3014 } else {
3015 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3016 pstat->bssrateset, &pattrib->pktlen);
3017 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3018 pstat->bssratelen - 8,
3019 pstat->bssrateset + 8, &pattrib->pktlen);
3020 }
3021
3022 if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
3023 /* FILL HT CAP INFO IE */
3024 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3025 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
3026 pnetwork->IELength);
3027 if (p && p[1]) {
3028 memcpy(pframe, p, p[1] + 2);
3029 pframe += (p[1] + 2);
3030 pattrib->pktlen += (p[1] + 2);
3031 }
3032
3033 /* FILL HT ADD INFO IE */
3034 /* p = hostapd_eid_ht_operation(hapd, p); */
3035 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
3036 pnetwork->IELength);
3037 if (p && p[1] > 0) {
3038 memcpy(pframe, p, p[1] + 2);
3039 pframe += (p[1] + 2);
3040 pattrib->pktlen += (p[1] + 2);
3041 }
3042 }
3043
3044 /* FILL WMM IE */
3045 if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
3046 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
3047 0x01, 0x01};
3048 int ie_len = 0;
3049
3050 for (p = ie; ; p += (ie_len + 2)) {
3051 p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
3052 pnetwork->IELength - (ie_len + 2));
3053 if (p)
3054 ie_len = p[1];
3055 else
3056 ie_len = 0;
3057 if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
3058 memcpy(pframe, p, ie_len + 2);
3059 pframe += (ie_len + 2);
3060 pattrib->pktlen += (ie_len + 2);
3061
3062 break;
3063 }
3064
3065 if (!p || ie_len == 0)
3066 break;
3067 }
3068 }
3069
3070 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3071 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3072 REALTEK_96B_IE, &pattrib->pktlen);
3073 }
3074
3075 pattrib->last_txcmdsz = pattrib->pktlen;
3076
3077 dump_mgntframe23a(padapter, pmgntframe);
3078 }
3079 #endif
3080
3081 static void issue_assocreq(struct rtw_adapter *padapter)
3082 {
3083 int ret = _FAIL;
3084 struct xmit_frame *pmgntframe;
3085 struct pkt_attrib *pattrib;
3086 unsigned char *pframe;
3087 const u8 *p;
3088 struct ieee80211_mgmt *mgmt;
3089 unsigned int i, j, index = 0;
3090 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
3091 struct registry_priv *pregpriv = &padapter->registrypriv;
3092 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3093 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3094 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3095 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3096 int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
3097 u8 *pie;
3098
3099 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3100 if (!pmgntframe)
3101 goto exit;
3102
3103 /* update attribute */
3104 pattrib = &pmgntframe->attrib;
3105 update_mgntframe_attrib23a(padapter, pattrib);
3106
3107 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3108
3109 pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
3110 mgmt = (struct ieee80211_mgmt *)pframe;
3111
3112 mgmt->frame_control =
3113 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
3114
3115 ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
3116 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3117 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3118
3119 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3120 pmlmeext->mgnt_seq++;
3121
3122 /* caps */
3123 put_unaligned_le16(pmlmeinfo->network.capability,
3124 &mgmt->u.assoc_req.capab_info);
3125 /* todo: listen interval for power saving */
3126 put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
3127
3128 pframe = mgmt->u.assoc_req.variable;
3129 pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
3130
3131 /* SSID */
3132 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
3133 pmlmeinfo->network.Ssid.ssid_len,
3134 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
3135
3136 /* supported rate & extended supported rate */
3137
3138 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
3139 /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
3140
3141 /* for JAPAN, channel 14 can only uses B Mode(CCK) */
3142 if (pmlmeext->cur_channel == 14)
3143 sta_bssrate_len = 4;
3144
3145 /* for (i = 0; i < sta_bssrate_len; i++) { */
3146 /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3147 /* */
3148
3149 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3150 if (pmlmeinfo->network.SupportedRates[i] == 0)
3151 break;
3152 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
3153 pmlmeinfo->network.SupportedRates[i]);
3154 }
3155
3156 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3157 if (pmlmeinfo->network.SupportedRates[i] == 0)
3158 break;
3159
3160 /* Check if the AP's supported rates are also
3161 supported by STA. */
3162 for (j = 0; j < sta_bssrate_len; j++) {
3163 /* Avoid the proprietary data rate (22Mbps) of
3164 Handlink WSG-4000 AP */
3165 if ((pmlmeinfo->network.SupportedRates[i] |
3166 IEEE80211_BASIC_RATE_MASK) ==
3167 (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
3168 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
3169 break;
3170 }
3171 }
3172
3173 if (j == sta_bssrate_len) {
3174 /* the rate is not supported by STA */
3175 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
3176 "STA!\n", __func__, i,
3177 pmlmeinfo->network.SupportedRates[i]);
3178 } else {
3179 /* the rate is supported by STA */
3180 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3181 }
3182 }
3183
3184 bssrate_len = index;
3185 DBG_8723A("bssrate_len = %d\n", bssrate_len);
3186
3187 if (bssrate_len == 0) {
3188 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
3189 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
3190 goto exit; /* don't connect to AP if no joint supported rate */
3191 }
3192
3193 if (bssrate_len > 8) {
3194 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
3195 bssrate, &pattrib->pktlen);
3196 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
3197 (bssrate_len - 8), (bssrate + 8),
3198 &pattrib->pktlen);
3199 } else
3200 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
3201 bssrate_len, bssrate, &pattrib->pktlen);
3202
3203 /* RSN */
3204
3205 pie = pmlmeinfo->network.IEs;
3206 pie_len = pmlmeinfo->network.IELength;
3207
3208 p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
3209 if (p)
3210 pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
3211 &pattrib->pktlen);
3212
3213 /* HT caps */
3214 if (padapter->mlmepriv.htpriv.ht_option) {
3215 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
3216
3217 if (p && !is_ap_in_tkip23a(padapter)) {
3218 struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
3219
3220 memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
3221
3222 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
3223 if (pregpriv->cbw40_enable == 0) {
3224 cap->cap_info &= ~cpu_to_le16(
3225 IEEE80211_HT_CAP_SGI_40 |
3226 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3227 } else {
3228 cap->cap_info |= cpu_to_le16(
3229 IEEE80211_HT_CAP_SUP_WIDTH_20_40);
3230 }
3231
3232 /* todo: disable SM power save mode */
3233 cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
3234
3235 rf_type = rtl8723a_get_rf_type(padapter);
3236 /* switch (pregpriv->rf_config) */
3237 switch (rf_type) {
3238 case RF_1T1R:
3239 /* RX STBC One spatial stream */
3240 if (pregpriv->rx_stbc)
3241 cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3242
3243 memcpy(&cap->mcs, MCS_rate_1R23A, 16);
3244 break;
3245
3246 case RF_2T2R:
3247 case RF_1T2R:
3248 default:
3249 /* enable for 2.4/5 GHz */
3250 if (pregpriv->rx_stbc == 0x3 ||
3251 (pmlmeext->cur_wireless_mode &
3252 WIRELESS_11_24N &&
3253 /* enable for 2.4GHz */
3254 pregpriv->rx_stbc == 0x1) ||
3255 (pmlmeext->cur_wireless_mode &
3256 WIRELESS_11_5N &&
3257 pregpriv->rx_stbc == 0x2) ||
3258 /* enable for 5GHz */
3259 pregpriv->wifi_spec == 1) {
3260 DBG_8723A("declare supporting RX "
3261 "STBC\n");
3262 /* RX STBC two spatial stream */
3263 cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
3264 }
3265 memcpy(&cap->mcs, MCS_rate_2R23A, 16);
3266 break;
3267 }
3268
3269 if (rtl8723a_BT_coexist(padapter) &&
3270 rtl8723a_BT_using_antenna_1(padapter)) {
3271 /* set to 8K */
3272 cap->ampdu_params_info &=
3273 ~IEEE80211_HT_AMPDU_PARM_FACTOR;
3274 /* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
3275 }
3276
3277 pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
3278 p[1], (u8 *)&pmlmeinfo->ht_cap,
3279 &pattrib->pktlen);
3280 }
3281 }
3282
3283 /* vendor specific IE, such as WPA, WMM, WPS */
3284 for (i = 0; i < pmlmeinfo->network.IELength;) {
3285 p = pmlmeinfo->network.IEs + i;
3286
3287 switch (p[0]) {
3288 case WLAN_EID_VENDOR_SPECIFIC:
3289 if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) ||
3290 !memcmp(p + 2, WMM_OUI23A, 4) ||
3291 !memcmp(p + 2, WPS_OUI23A, 4)) {
3292 u8 plen = p[1];
3293
3294 if (!padapter->registrypriv.wifi_spec) {
3295 /* Commented by Kurt 20110629 */
3296 /* In some older APs, WPS handshake */
3297 /* would be fail if we append vender
3298 extensions informations to AP */
3299 if (!memcmp(p + 2, WPS_OUI23A, 4))
3300 plen = 14;
3301 }
3302 pframe = rtw_set_ie23a(pframe,
3303 WLAN_EID_VENDOR_SPECIFIC,
3304 plen, p + 2,
3305 &pattrib->pktlen);
3306 }
3307 break;
3308
3309 default:
3310 break;
3311 }
3312
3313 i += p[1] + 2;
3314 }
3315
3316 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3317 pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
3318 REALTEK_96B_IE, &pattrib->pktlen);
3319
3320 pattrib->last_txcmdsz = pattrib->pktlen;
3321 dump_mgntframe23a(padapter, pmgntframe);
3322
3323 ret = _SUCCESS;
3324
3325 exit:
3326 pmlmepriv->assoc_req_len = 0;
3327 if (ret == _SUCCESS) {
3328 kfree(pmlmepriv->assoc_req);
3329 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
3330 if (pmlmepriv->assoc_req) {
3331 memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
3332 pmlmepriv->assoc_req_len = pattrib->pktlen;
3333 }
3334 } else
3335 kfree(pmlmepriv->assoc_req);
3336 }
3337
3338 /* when wait_ack is true, this function should be called at process context */
3339 static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3340 unsigned int power_mode, int wait_ack)
3341 {
3342 int ret = _FAIL;
3343 struct xmit_frame *pmgntframe;
3344 struct pkt_attrib *pattrib;
3345 unsigned char *pframe;
3346 struct ieee80211_hdr *pwlanhdr;
3347 struct xmit_priv *pxmitpriv;
3348 struct mlme_ext_priv *pmlmeext;
3349 struct mlme_ext_info *pmlmeinfo;
3350
3351 /* DBG_8723A("%s:%d\n", __func__, power_mode); */
3352
3353 if (!padapter)
3354 goto exit;
3355
3356 pxmitpriv = &padapter->xmitpriv;
3357 pmlmeext = &padapter->mlmeextpriv;
3358 pmlmeinfo = &pmlmeext->mlmext_info;
3359
3360 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3361 if (!pmgntframe)
3362 goto exit;
3363
3364 /* update attribute */
3365 pattrib = &pmgntframe->attrib;
3366 update_mgntframe_attrib23a(padapter, pattrib);
3367 pattrib->retry_ctrl = false;
3368
3369 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3370
3371 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3372 pwlanhdr = (struct ieee80211_hdr *)pframe;
3373
3374 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3375 IEEE80211_STYPE_NULLFUNC);
3376
3377 if ((pmlmeinfo->state&0x03) == MSR_AP)
3378 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3379 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3380 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3381
3382 if (power_mode)
3383 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
3384
3385 ether_addr_copy(pwlanhdr->addr1, da);
3386 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3387 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3388
3389 pwlanhdr->seq_ctrl =
3390 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3391 pmlmeext->mgnt_seq++;
3392
3393 pframe += sizeof(struct ieee80211_hdr_3addr);
3394 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3395
3396 pattrib->last_txcmdsz = pattrib->pktlen;
3397
3398 if (wait_ack)
3399 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3400 else {
3401 dump_mgntframe23a(padapter, pmgntframe);
3402 ret = _SUCCESS;
3403 }
3404
3405 exit:
3406 return ret;
3407 }
3408
3409 /* when wait_ms >0 , this function should be called at process context */
3410 /* da == NULL for station mode */
3411 int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3412 unsigned int power_mode, int try_cnt, int wait_ms)
3413 {
3414 int ret;
3415 int i = 0;
3416 unsigned long start = jiffies;
3417 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3418 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3419
3420 /* da == NULL, assume it's null data for sta to ap*/
3421 if (da == NULL)
3422 da = get_my_bssid23a(&pmlmeinfo->network);
3423
3424 do {
3425 ret = _issue_nulldata23a(padapter, da, power_mode,
3426 wait_ms > 0 ? true : false);
3427
3428 i++;
3429
3430 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3431 break;
3432
3433 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3434 msleep(wait_ms);
3435
3436 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3437
3438 if (ret != _FAIL) {
3439 ret = _SUCCESS;
3440 goto exit;
3441 }
3442
3443 if (try_cnt && wait_ms) {
3444 if (da)
3445 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3446 __func__, padapter->pnetdev->name,
3447 da, rtw_get_oper_ch23a(padapter),
3448 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3449 jiffies_to_msecs(jiffies - start));
3450 else
3451 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3452 __func__, padapter->pnetdev->name,
3453 rtw_get_oper_ch23a(padapter),
3454 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3455 jiffies_to_msecs(jiffies - start));
3456 }
3457 exit:
3458 return ret;
3459 }
3460
3461 /* when wait_ack is true, this function should be called at process context */
3462 static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
3463 unsigned char *da, u16 tid, int wait_ack)
3464 {
3465 int ret = _FAIL;
3466 struct xmit_frame *pmgntframe;
3467 struct pkt_attrib *pattrib;
3468 unsigned char *pframe;
3469 struct ieee80211_qos_hdr *pwlanhdr;
3470 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3471 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3472 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3473
3474 DBG_8723A("%s\n", __func__);
3475
3476 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3477 if (!pmgntframe)
3478 goto exit;
3479
3480 /* update attribute */
3481 pattrib = &pmgntframe->attrib;
3482 update_mgntframe_attrib23a(padapter, pattrib);
3483
3484 pattrib->hdrlen += 2;
3485 pattrib->qos_en = true;
3486 pattrib->eosp = 1;
3487 pattrib->ack_policy = 0;
3488 pattrib->mdata = 0;
3489
3490 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3491
3492 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3493 pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
3494
3495 pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
3496 IEEE80211_STYPE_QOS_NULLFUNC);
3497
3498 if ((pmlmeinfo->state&0x03) == MSR_AP)
3499 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
3500 else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
3501 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
3502
3503 if (pattrib->mdata)
3504 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
3505
3506 pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK);
3507 pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) &
3508 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
3509 if (pattrib->eosp)
3510 pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
3511
3512 ether_addr_copy(pwlanhdr->addr1, da);
3513 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3514 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
3515
3516 pwlanhdr->seq_ctrl =
3517 cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3518 pmlmeext->mgnt_seq++;
3519
3520 pframe += sizeof(struct ieee80211_qos_hdr);
3521 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3522
3523 pattrib->last_txcmdsz = pattrib->pktlen;
3524
3525 if (wait_ack)
3526 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3527 else {
3528 dump_mgntframe23a(padapter, pmgntframe);
3529 ret = _SUCCESS;
3530 }
3531
3532 exit:
3533 return ret;
3534 }
3535
3536 /* when wait_ms >0 , this function should be called at process context */
3537 /* da == NULL for station mode */
3538 int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
3539 u16 tid, int try_cnt, int wait_ms)
3540 {
3541 int ret;
3542 int i = 0;
3543 unsigned long start = jiffies;
3544 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3545 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3546
3547 /* da == NULL, assume it's null data for sta to ap*/
3548 if (da == NULL)
3549 da = get_my_bssid23a(&pmlmeinfo->network);
3550
3551 do {
3552 ret = _issue_qos_nulldata23a(padapter, da, tid,
3553 wait_ms > 0 ? true : false);
3554
3555 i++;
3556
3557 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3558 break;
3559
3560 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3561 msleep(wait_ms);
3562 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3563
3564 if (ret != _FAIL) {
3565 ret = _SUCCESS;
3566 goto exit;
3567 }
3568
3569 if (try_cnt && wait_ms) {
3570 if (da)
3571 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3572 __func__, padapter->pnetdev->name,
3573 da, rtw_get_oper_ch23a(padapter),
3574 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3575 jiffies_to_msecs(jiffies - start));
3576 else
3577 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3578 __func__, padapter->pnetdev->name,
3579 rtw_get_oper_ch23a(padapter),
3580 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3581 jiffies_to_msecs(jiffies - start));
3582 }
3583 exit:
3584 return ret;
3585 }
3586
3587 static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
3588 unsigned short reason, u8 wait_ack)
3589 {
3590 struct xmit_frame *pmgntframe;
3591 struct pkt_attrib *pattrib;
3592 struct ieee80211_mgmt *mgmt;
3593 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3594 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3595 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3596 int ret = _FAIL;
3597
3598 /* DBG_8723A("%s to %pM\n", __func__, da); */
3599
3600 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3601 if (!pmgntframe)
3602 goto exit;
3603
3604 /* update attribute */
3605 pattrib = &pmgntframe->attrib;
3606 update_mgntframe_attrib23a(padapter, pattrib);
3607 pattrib->retry_ctrl = false;
3608
3609 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3610
3611 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3612
3613 mgmt->frame_control =
3614 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
3615
3616 ether_addr_copy(mgmt->da, da);
3617 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3618 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3619
3620 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3621 pmlmeext->mgnt_seq++;
3622
3623 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
3624
3625 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
3626
3627 pattrib->last_txcmdsz = pattrib->pktlen;
3628
3629 if (wait_ack)
3630 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
3631 else {
3632 dump_mgntframe23a(padapter, pmgntframe);
3633 ret = _SUCCESS;
3634 }
3635
3636 exit:
3637 return ret;
3638 }
3639
3640 int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
3641 unsigned short reason)
3642 {
3643 DBG_8723A("%s to %pM\n", __func__, da);
3644 return _issue_deauth(padapter, da, reason, false);
3645 }
3646
3647 static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
3648 unsigned short reason, int try_cnt, int wait_ms)
3649 {
3650 int ret;
3651 int i = 0;
3652 unsigned long start = jiffies;
3653
3654 do {
3655 ret = _issue_deauth(padapter, da, reason,
3656 wait_ms >0 ? true : false);
3657
3658 i++;
3659
3660 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3661 break;
3662
3663 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3664 msleep(wait_ms);
3665
3666 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
3667
3668 if (ret != _FAIL) {
3669 ret = _SUCCESS;
3670 goto exit;
3671 }
3672
3673 if (try_cnt && wait_ms) {
3674 if (da)
3675 DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
3676 __func__, padapter->pnetdev->name,
3677 da, rtw_get_oper_ch23a(padapter),
3678 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3679 jiffies_to_msecs(jiffies - start));
3680 else
3681 DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
3682 __func__, padapter->pnetdev->name,
3683 rtw_get_oper_ch23a(padapter),
3684 ret == _SUCCESS ? ", acked" : "", i, try_cnt,
3685 jiffies_to_msecs(jiffies - start));
3686 }
3687 exit:
3688 return ret;
3689 }
3690
3691 void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
3692 u8 *ra, u8 new_ch, u8 ch_offset)
3693 {
3694 struct xmit_frame *pmgntframe;
3695 struct pkt_attrib *pattrib;
3696 unsigned char *pframe;
3697 struct ieee80211_mgmt *mgmt;
3698 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3699 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3700
3701 DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
3702 __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
3703
3704 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3705 if (!pmgntframe)
3706 return;
3707
3708 /* update attribute */
3709 pattrib = &pmgntframe->attrib;
3710 update_mgntframe_attrib23a(padapter, pattrib);
3711
3712 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3713
3714 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3715
3716 mgmt->frame_control =
3717 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3718
3719 ether_addr_copy(mgmt->da, ra); /* RA */
3720 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */
3721 ether_addr_copy(mgmt->bssid, ra); /* DA = RA */
3722
3723 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3724 pmlmeext->mgnt_seq++;
3725
3726 mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
3727 mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
3728
3729 pframe = mgmt->u.action.u.chan_switch.variable;
3730 pattrib->pktlen = offsetof(struct ieee80211_mgmt,
3731 u.action.u.chan_switch.variable);
3732
3733 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
3734 new_ch, 0);
3735 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
3736 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
3737
3738 pattrib->last_txcmdsz = pattrib->pktlen;
3739
3740 dump_mgntframe23a(padapter, pmgntframe);
3741 }
3742
3743 void issue_action_BA23a(struct rtw_adapter *padapter,
3744 const unsigned char *raddr,
3745 unsigned char action, unsigned short status)
3746 {
3747 u16 start_seq;
3748 u16 BA_para_set;
3749 u16 BA_starting_seqctrl;
3750 u16 BA_para;
3751 int max_rx_ampdu_factor;
3752 struct xmit_frame *pmgntframe;
3753 struct pkt_attrib *pattrib;
3754 struct ieee80211_mgmt *mgmt;
3755 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3756 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3757 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3758 struct sta_info *psta;
3759 struct sta_priv *pstapriv = &padapter->stapriv;
3760 struct registry_priv *pregpriv = &padapter->registrypriv;
3761 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
3762
3763 DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
3764
3765 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3766 if (!pmgntframe)
3767 return;
3768
3769 /* update attribute */
3770 pattrib = &pmgntframe->attrib;
3771 update_mgntframe_attrib23a(padapter, pattrib);
3772
3773 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3774
3775 mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
3776
3777 mgmt->frame_control =
3778 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
3779
3780 ether_addr_copy(mgmt->da, raddr);
3781 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
3782 ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
3783
3784 mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
3785 pmlmeext->mgnt_seq++;
3786
3787 mgmt->u.action.category = WLAN_CATEGORY_BACK;
3788
3789 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
3790
3791 switch (action) {
3792 case WLAN_ACTION_ADDBA_REQ:
3793 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
3794
3795 mgmt->u.action.u.addba_req.action_code = action;
3796
3797 do {
3798 pmlmeinfo->dialogToken++;
3799 } while (pmlmeinfo->dialogToken == 0);
3800
3801 mgmt->u.action.u.addba_req.dialog_token =
3802 pmlmeinfo->dialogToken;
3803
3804 if (rtl8723a_BT_coexist(padapter) &&
3805 rtl8723a_BT_using_antenna_1(padapter) &&
3806 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3807 memcmp(raddr, tendaAPMac, 3))) {
3808 /* A-MSDU NOT Supported */
3809 BA_para_set = 0;
3810 /* immediate Block Ack */
3811 BA_para_set |= (1 << 1) &
3812 IEEE80211_ADDBA_PARAM_POLICY_MASK;
3813 /* TID */
3814 BA_para_set |= (status << 2) &
3815 IEEE80211_ADDBA_PARAM_TID_MASK;
3816 /* max buffer size is 8 MSDU */
3817 BA_para_set |= (8 << 6) &
3818 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3819 } else {
3820 /* immediate ack & 64 buffer size */
3821 BA_para_set = 0x1002 | ((status & 0xf) << 2);
3822 }
3823
3824 put_unaligned_le16(BA_para_set,
3825 &mgmt->u.action.u.addba_req.capab);
3826
3827 /* 5ms */
3828 put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
3829
3830 psta = rtw_get_stainfo23a(pstapriv, raddr);
3831 if (psta) {
3832 int idx;
3833
3834 idx = status & 0x07;
3835 start_seq =
3836 (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
3837
3838 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
3839 start_seq, idx);
3840
3841 psta->BA_starting_seqctrl[idx] = start_seq;
3842
3843 BA_starting_seqctrl = start_seq << 4;
3844 } else
3845 BA_starting_seqctrl = 0;
3846
3847 put_unaligned_le16(BA_starting_seqctrl,
3848 &mgmt->u.action.u.addba_req.start_seq_num);
3849
3850 break;
3851
3852 case WLAN_ACTION_ADDBA_RESP:
3853 pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
3854
3855 mgmt->u.action.u.addba_resp.action_code = action;
3856 mgmt->u.action.u.addba_resp.dialog_token =
3857 pmlmeinfo->ADDBA_req.dialog_token;
3858 put_unaligned_le16(status,
3859 &mgmt->u.action.u.addba_resp.status);
3860
3861 GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
3862 &max_rx_ampdu_factor);
3863
3864 BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
3865 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
3866 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3867 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
3868 BA_para_set = BA_para | 0x0800; /* 32 buffer size */
3869 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
3870 BA_para_set = BA_para | 0x0400; /* 16 buffer size */
3871 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
3872 BA_para_set = BA_para | 0x0200; /* 8 buffer size */
3873 else
3874 BA_para_set = BA_para | 0x1000; /* 64 buffer size */
3875
3876 if (rtl8723a_BT_coexist(padapter) &&
3877 rtl8723a_BT_using_antenna_1(padapter) &&
3878 (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
3879 memcmp(raddr, tendaAPMac, 3))) {
3880 /* max buffer size is 8 MSDU */
3881 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3882 BA_para_set |= (8 << 6) &
3883 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3884 }
3885
3886 if (pregpriv->ampdu_amsdu == 0)/* disabled */
3887 BA_para_set &= ~BIT(0);
3888 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3889 BA_para_set |= BIT(0);
3890
3891 put_unaligned_le16(BA_para_set,
3892 &mgmt->u.action.u.addba_resp.capab);
3893
3894 mgmt->u.action.u.addba_resp.timeout
3895 = pmlmeinfo->ADDBA_req.BA_timeout_value;
3896
3897 pattrib->pktlen += 8;
3898 break;
3899 case WLAN_ACTION_DELBA:
3900 pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
3901
3902 mgmt->u.action.u.delba.action_code = action;
3903 BA_para_set = (status & 0x1F) << 3;
3904 mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
3905 mgmt->u.action.u.delba.reason_code =
3906 cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
3907
3908 pattrib->pktlen += 5;
3909 break;
3910 default:
3911 break;
3912 }
3913
3914 pattrib->last_txcmdsz = pattrib->pktlen;
3915
3916 dump_mgntframe23a(padapter, pmgntframe);
3917 }
3918
3919 int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
3920 {
3921 struct sta_priv *pstapriv = &padapter->stapriv;
3922 struct sta_info *psta = NULL;
3923 /* struct recv_reorder_ctrl *preorder_ctrl; */
3924 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3925 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3926 u16 tid;
3927
3928 if ((pmlmeinfo->state&0x03) != MSR_AP)
3929 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3930 return _SUCCESS;
3931
3932 psta = rtw_get_stainfo23a(pstapriv, addr);
3933 if (psta == NULL)
3934 return _SUCCESS;
3935
3936 if (initiator == 0) { /* recipient */
3937 for (tid = 0; tid < MAXTID; tid++) {
3938 if (psta->recvreorder_ctrl[tid].enable == true) {
3939 DBG_8723A("rx agg disable tid(%d)\n", tid);
3940 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3941 psta->recvreorder_ctrl[tid].enable = false;
3942 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3943 }
3944 }
3945 } else if (initiator == 1) { /* originator */
3946 for (tid = 0; tid < MAXTID; tid++) {
3947 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
3948 DBG_8723A("tx agg disable tid(%d)\n", tid);
3949 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
3950 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3951 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3952
3953 }
3954 }
3955 }
3956 return _SUCCESS;
3957 }
3958
3959 int send_beacon23a(struct rtw_adapter *padapter)
3960 {
3961 bool bxmitok;
3962 int issue = 0;
3963 int poll = 0;
3964 unsigned long start = jiffies;
3965 unsigned int passing_time;
3966
3967 rtl8723a_bcn_valid(padapter);
3968 do {
3969 issue_beacon23a(padapter, 100);
3970 issue++;
3971 do {
3972 yield();
3973 bxmitok = rtl8723a_get_bcn_valid(padapter);
3974 poll++;
3975 } while ((poll % 10) != 0 && !bxmitok &&
3976 !padapter->bSurpriseRemoved &&
3977 !padapter->bDriverStopped);
3978
3979 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
3980 !padapter->bDriverStopped);
3981
3982 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
3983 return _FAIL;
3984
3985 passing_time = jiffies_to_msecs(jiffies - start);
3986
3987 if (!bxmitok) {
3988 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
3989 return _FAIL;
3990 } else {
3991
3992 if (passing_time > 100 || issue > 3)
3993 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
3994 __func__, issue, poll, passing_time);
3995 return _SUCCESS;
3996 }
3997 }
3998
3999 /****************************************************************************
4000
4001 Following are some utitity functions for WiFi MLME
4002
4003 *****************************************************************************/
4004
4005 bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
4006 {
4007
4008 int i = 0;
4009 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
4010 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
4011 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
4012 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
4013 161, 163, 165};
4014 for (i = 0; i < sizeof(Channel_5G); i++)
4015 if (channel == Channel_5G[i])
4016 return true;
4017 return false;
4018 }
4019
4020 static void rtw_site_survey(struct rtw_adapter *padapter)
4021 {
4022 unsigned char survey_channel = 0;
4023 enum rt_scan_type ScanType = SCAN_PASSIVE;
4024 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4025 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4026 struct rtw_ieee80211_channel *ch;
4027
4028 if (pmlmeext->sitesurvey_res.channel_idx <
4029 pmlmeext->sitesurvey_res.ch_num) {
4030 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4031 survey_channel = ch->hw_value;
4032 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
4033 SCAN_PASSIVE : SCAN_ACTIVE;
4034 }
4035
4036 if (survey_channel != 0) {
4037 /* PAUSE 4-AC Queue when site_survey */
4038 if (pmlmeext->sitesurvey_res.channel_idx == 0)
4039 set_channel_bwmode23a(padapter, survey_channel,
4040 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
4041 HT_CHANNEL_WIDTH_20);
4042 else
4043 SelectChannel23a(padapter, survey_channel);
4044
4045 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
4046 {
4047 int i;
4048
4049 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
4050 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
4051 /* todo: to issue two probe req??? */
4052 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4053 /* msleep(SURVEY_TO>>1); */
4054 issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
4055 }
4056 }
4057
4058 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4059 /* todo: to issue two probe req??? */
4060 issue_probereq(padapter, NULL, NULL);
4061 /* msleep(SURVEY_TO>>1); */
4062 issue_probereq(padapter, NULL, NULL);
4063 }
4064 }
4065
4066 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
4067 } else {
4068 /* channel number is 0 or this channel is not valid. */
4069 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4070
4071 /* switch back to the original channel */
4072
4073 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
4074 pmlmeext->cur_ch_offset,
4075 pmlmeext->cur_bwmode);
4076
4077 /* flush 4-AC Queue after rtw_site_survey */
4078 /* val8 = 0; */
4079
4080 /* config MSR */
4081 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4082
4083 /* restore RX GAIN */
4084 rtl8723a_set_initial_gain(padapter, 0xff);
4085 /* turn on dynamic functions */
4086 rtl8723a_odm_support_ability_restore(padapter);
4087
4088 if (is_client_associated_to_ap23a(padapter) == true)
4089 issue_nulldata23a(padapter, NULL, 0, 3, 500);
4090
4091 rtl8723a_mlme_sitesurvey(padapter, 0);
4092
4093 report_surveydone_event23a(padapter);
4094
4095 pmlmeext->chan_scan_time = SURVEY_TO;
4096 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4097 }
4098 }
4099
4100 /* collect bss info from Beacon and Probe request/response frames. */
4101 static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
4102 struct recv_frame *precv_frame)
4103 {
4104 struct sk_buff *skb = precv_frame->pkt;
4105 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
4106 struct registry_priv *pregistrypriv = &padapter->registrypriv;
4107 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4108 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4109 struct wlan_bssid_ex *bssid;
4110 const u8 *p;
4111 u8 *pie;
4112 unsigned int length;
4113 int i;
4114
4115 length = skb->len;
4116
4117 bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
4118 if (!bssid)
4119 return NULL;
4120
4121 if (ieee80211_is_beacon(mgmt->frame_control)) {
4122 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4123 pie = mgmt->u.beacon.variable;
4124 bssid->reserved = 1;
4125 bssid->capability =
4126 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4127 bssid->beacon_interval =
4128 get_unaligned_le16(&mgmt->u.beacon.beacon_int);
4129 bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
4130 } else if (ieee80211_is_probe_req(mgmt->frame_control)) {
4131 length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
4132 pie = mgmt->u.probe_req.variable;
4133 bssid->reserved = 2;
4134 bssid->capability = 0;
4135 bssid->beacon_interval =
4136 padapter->registrypriv.dev_network.beacon_interval;
4137 bssid->tsf = 0;
4138 } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
4139 length -=
4140 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
4141 pie = mgmt->u.probe_resp.variable;
4142 bssid->reserved = 3;
4143 bssid->capability =
4144 get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
4145 bssid->beacon_interval =
4146 get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
4147 bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
4148 } else {
4149 length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
4150 pie = mgmt->u.beacon.variable;
4151 bssid->reserved = 0;
4152 bssid->capability =
4153 get_unaligned_le16(&mgmt->u.beacon.capab_info);
4154 bssid->beacon_interval =
4155 padapter->registrypriv.dev_network.beacon_interval;
4156 bssid->tsf = 0;
4157 }
4158
4159 if (length > MAX_IE_SZ) {
4160 /* DBG_8723A("IE too long for survey event\n"); */
4161 kfree(bssid);
4162 return NULL;
4163 }
4164
4165 bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
4166
4167 /* below is to copy the information element */
4168 bssid->IELength = length;
4169 memcpy(bssid->IEs, pie, bssid->IELength);
4170
4171 /* get the signal strength */
4172 /* in dBM.raw data */
4173 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
4174 bssid->SignalQuality =
4175 precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
4176 bssid->SignalStrength =
4177 precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
4178
4179 /* checking SSID */
4180 p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
4181
4182 if (!p) {
4183 DBG_8723A("marc: cannot find SSID for survey event\n");
4184 goto fail;
4185 }
4186
4187 if (p[1] > IEEE80211_MAX_SSID_LEN) {
4188 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4189 "event\n", __func__, __LINE__, p[1]);
4190 goto fail;
4191 }
4192 memcpy(bssid->Ssid.ssid, p + 2, p[1]);
4193 bssid->Ssid.ssid_len = p[1];
4194
4195 /* checking rate info... */
4196 i = 0;
4197 p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
4198 if (p) {
4199 if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
4200 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4201 "event\n", __func__, __LINE__, p[1]);
4202 goto fail;
4203 }
4204 memcpy(bssid->SupportedRates, p + 2, p[1]);
4205 i = p[1];
4206 }
4207
4208 p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
4209 bssid->IELength);
4210 if (p) {
4211 if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4212 DBG_8723A("%s()-%d: IE too long (%d) for survey "
4213 "event\n", __func__, __LINE__, p[1]);
4214 goto fail;
4215 }
4216 memcpy(bssid->SupportedRates + i, p + 2, p[1]);
4217 }
4218
4219 /* Checking for DSConfig */
4220 p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
4221
4222 bssid->DSConfig = 0;
4223
4224 if (p) {
4225 bssid->DSConfig = p[2];
4226 } else {/* In 5G, some ap do not have DSSET IE */
4227 /* checking HT info for channel */
4228 p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
4229 bssid->IELength);
4230 if (p) {
4231 struct ieee80211_ht_operation *HT_info =
4232 (struct ieee80211_ht_operation *)(p + 2);
4233 bssid->DSConfig = HT_info->primary_chan;
4234 } else /* use current channel */
4235 bssid->DSConfig = rtw_get_oper_ch23a(padapter);
4236 }
4237
4238 if (ieee80211_is_probe_req(mgmt->frame_control)) {
4239 /* FIXME */
4240 bssid->ifmode = NL80211_IFTYPE_STATION;
4241 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4242 bssid->Privacy = 1;
4243 return bssid;
4244 }
4245
4246 if (bssid->capability & WLAN_CAPABILITY_ESS) {
4247 bssid->ifmode = NL80211_IFTYPE_STATION;
4248 ether_addr_copy(bssid->MacAddress, mgmt->sa);
4249 } else {
4250 bssid->ifmode = NL80211_IFTYPE_ADHOC;
4251 ether_addr_copy(bssid->MacAddress, mgmt->bssid);
4252 }
4253
4254 if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
4255 bssid->Privacy = 1;
4256 else
4257 bssid->Privacy = 0;
4258
4259 bssid->ATIMWindow = 0;
4260
4261 /* 20/40 BSS Coexistence check */
4262 if (pregistrypriv->wifi_spec == 1 &&
4263 pmlmeinfo->bwmode_updated == false) {
4264 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4265
4266 p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
4267 bssid->IELength);
4268 if (p && p[1] > 0) {
4269 struct ieee80211_ht_cap *pHT_caps;
4270
4271 pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
4272
4273 if (pHT_caps->cap_info &
4274 cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
4275 pmlmepriv->num_FortyMHzIntolerant++;
4276 } else
4277 pmlmepriv->num_sta_no_ht++;
4278 }
4279
4280
4281 /* mark bss info receiving from nearby channel as SignalQuality 101 */
4282 if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
4283 bssid->SignalQuality = 101;
4284
4285 return bssid;
4286 fail:
4287 kfree (bssid);
4288 return NULL;
4289 }
4290
4291 static void start_create_ibss(struct rtw_adapter *padapter)
4292 {
4293 unsigned short caps;
4294 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4295 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4296 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4297
4298 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4299 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4300
4301 /* update wireless mode */
4302 update_wireless_mode23a(padapter);
4303
4304 /* update capability */
4305 caps = pnetwork->capability;
4306 update_capinfo23a(padapter, caps);
4307 if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */
4308 rtl8723a_set_sec_cfg(padapter, 0xcf);
4309
4310 /* switch channel */
4311 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4312 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
4313
4314 rtl8723a_SetBeaconRelatedRegisters(padapter);
4315
4316 /* set msr to MSR_ADHOC */
4317 pmlmeinfo->state = MSR_ADHOC;
4318 rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
4319
4320 /* issue beacon */
4321 if (send_beacon23a(padapter) == _FAIL) {
4322 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
4323 "issuing beacon frame fail....\n");
4324
4325 report_join_res23a(padapter, -1);
4326 pmlmeinfo->state = MSR_NOLINK;
4327 } else {
4328 hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
4329 hw_var_set_mlme_join(padapter, 0);
4330
4331 report_join_res23a(padapter, 1);
4332 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4333 }
4334 } else {
4335 DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
4336 return;
4337 }
4338 }
4339
4340 static void start_clnt_join(struct rtw_adapter *padapter)
4341 {
4342 unsigned short caps;
4343 u8 val8;
4344 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4345 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4346 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
4347 int beacon_timeout;
4348
4349 pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
4350 pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
4351
4352 /* update wireless mode */
4353 update_wireless_mode23a(padapter);
4354
4355 /* update capability */
4356 caps = pnetwork->capability;
4357 update_capinfo23a(padapter, caps);
4358 if (caps & WLAN_CAPABILITY_ESS) {
4359 /* switch channel */
4360 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4361
4362 rtl8723a_set_media_status(padapter, MSR_INFRA);
4363
4364 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
4365 0xcc: 0xcf;
4366
4367 rtl8723a_set_sec_cfg(padapter, val8);
4368
4369 /* switch channel */
4370 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
4371
4372 /* here wait for receiving the beacon to start auth */
4373 /* and enable a timer */
4374 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
4375 set_link_timer(pmlmeext, beacon_timeout);
4376 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
4377 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
4378 pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
4379 } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
4380 rtl8723a_set_media_status(padapter, MSR_ADHOC);
4381
4382 rtl8723a_set_sec_cfg(padapter, 0xcf);
4383
4384 /* switch channel */
4385 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4386
4387 rtl8723a_SetBeaconRelatedRegisters(padapter);
4388
4389 pmlmeinfo->state = MSR_ADHOC;
4390
4391 report_join_res23a(padapter, 1);
4392 } else {
4393 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
4394 return;
4395 }
4396 }
4397
4398 static void start_clnt_auth(struct rtw_adapter *padapter)
4399 {
4400 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4401 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4402
4403 del_timer_sync(&pmlmeext->link_timer);
4404
4405 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4406 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4407
4408 pmlmeinfo->auth_seq = 1;
4409 pmlmeinfo->reauth_count = 0;
4410 pmlmeinfo->reassoc_count = 0;
4411 pmlmeinfo->link_count = 0;
4412 pmlmeext->retry = 0;
4413
4414 /* Because of AP's not receiving deauth before */
4415 /* AP may: 1)not response auth or 2)deauth us after link is complete */
4416 /* issue deauth before issuing auth to deal with the situation */
4417 /* Commented by Albert 2012/07/21 */
4418 /* For the Win8 P2P connection, it will be hard to have a
4419 successful connection if this Wi-Fi doesn't connect to it. */
4420 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
4421 WLAN_REASON_DEAUTH_LEAVING);
4422
4423 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
4424 issue_auth(padapter, NULL, 0);
4425
4426 set_link_timer(pmlmeext, REAUTH_TO);
4427 }
4428
4429 static void start_clnt_assoc(struct rtw_adapter *padapter)
4430 {
4431 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4432 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4433
4434 del_timer_sync(&pmlmeext->link_timer);
4435
4436 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4437 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4438
4439 issue_assocreq(padapter);
4440
4441 set_link_timer(pmlmeext, REASSOC_TO);
4442 }
4443
4444 int receive_disconnect23a(struct rtw_adapter *padapter,
4445 unsigned char *MacAddr, unsigned short reason)
4446 {
4447 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4448 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4449
4450 /* check A3 */
4451 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
4452 return _SUCCESS;
4453
4454 DBG_8723A("%s\n", __func__);
4455
4456 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
4457 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4458 pmlmeinfo->state = MSR_NOLINK;
4459 report_del_sta_event23a(padapter, MacAddr, reason);
4460
4461 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4462 pmlmeinfo->state = MSR_NOLINK;
4463 report_join_res23a(padapter, -2);
4464 }
4465 }
4466
4467 return _SUCCESS;
4468 }
4469
4470 static void process_80211d(struct rtw_adapter *padapter,
4471 struct wlan_bssid_ex *bssid)
4472 {
4473 struct registry_priv *pregistrypriv;
4474 struct mlme_ext_priv *pmlmeext;
4475 struct rt_channel_info *chplan_new;
4476 u8 channel;
4477 u8 i;
4478
4479 pregistrypriv = &padapter->registrypriv;
4480 pmlmeext = &padapter->mlmeextpriv;
4481
4482 /* Adjust channel plan by AP Country IE */
4483 if (pregistrypriv->enable80211d &&
4484 !pmlmeext->update_channel_plan_by_ap_done) {
4485 const u8 *ie, *p;
4486 struct rt_channel_plan chplan_ap;
4487 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4488 u8 country[4];
4489 u8 fcn; /* first channel number */
4490 u8 noc; /* number of channel */
4491 u8 j, k;
4492
4493 ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
4494 bssid->IELength);
4495 if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
4496 return;
4497
4498 p = ie + 2;
4499 ie += ie[1];
4500 ie += 2;
4501
4502 memcpy(country, p, 3);
4503 country[3] = '\0';
4504
4505 p += 3;
4506 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4507 "%s: 802.11d country =%s\n", __func__, country);
4508
4509 i = 0;
4510 while ((ie - p) >= 3) {
4511 fcn = *(p++);
4512 noc = *(p++);
4513 p++;
4514
4515 for (j = 0; j < noc; j++) {
4516 if (fcn <= 14)
4517 channel = fcn + j; /* 2.4 GHz */
4518 else
4519 channel = fcn + j * 4; /* 5 GHz */
4520
4521 chplan_ap.Channel[i++] = channel;
4522 }
4523 }
4524 chplan_ap.Len = i;
4525
4526 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4527 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4528 chplan_new = pmlmeext->channel_set;
4529
4530 i = j = k = 0;
4531 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4532 do {
4533 if (i == MAX_CHANNEL_NUM ||
4534 chplan_sta[i].ChannelNum == 0 ||
4535 chplan_sta[i].ChannelNum > 14)
4536 break;
4537
4538 if (j == chplan_ap.Len ||
4539 chplan_ap.Channel[j] > 14)
4540 break;
4541
4542 if (chplan_sta[i].ChannelNum ==
4543 chplan_ap.Channel[j]) {
4544 chplan_new[k].ChannelNum =
4545 chplan_ap.Channel[j];
4546 chplan_new[k].ScanType = SCAN_ACTIVE;
4547 i++;
4548 j++;
4549 k++;
4550 } else if (chplan_sta[i].ChannelNum <
4551 chplan_ap.Channel[j]) {
4552 chplan_new[k].ChannelNum =
4553 chplan_sta[i].ChannelNum;
4554 chplan_new[k].ScanType =
4555 SCAN_PASSIVE;
4556 i++;
4557 k++;
4558 } else if (chplan_sta[i].ChannelNum >
4559 chplan_ap.Channel[j]) {
4560 chplan_new[k].ChannelNum =
4561 chplan_ap.Channel[j];
4562 chplan_new[k].ScanType =
4563 SCAN_ACTIVE;
4564 j++;
4565 k++;
4566 }
4567 } while (1);
4568
4569 /* change AP not support channel to Passive scan */
4570 while (i < MAX_CHANNEL_NUM &&
4571 chplan_sta[i].ChannelNum != 0 &&
4572 chplan_sta[i].ChannelNum <= 14) {
4573 chplan_new[k].ChannelNum =
4574 chplan_sta[i].ChannelNum;
4575 chplan_new[k].ScanType = SCAN_PASSIVE;
4576 i++;
4577 k++;
4578 }
4579
4580 /* add channel AP supported */
4581 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
4582 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4583 chplan_new[k].ScanType = SCAN_ACTIVE;
4584 j++;
4585 k++;
4586 }
4587 } else {
4588 /* keep original STA 2.4G channel plan */
4589 while (i < MAX_CHANNEL_NUM &&
4590 chplan_sta[i].ChannelNum != 0 &&
4591 chplan_sta[i].ChannelNum <= 14) {
4592 chplan_new[k].ChannelNum =
4593 chplan_sta[i].ChannelNum;
4594 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4595 i++;
4596 k++;
4597 }
4598
4599 /* skip AP 2.4G channel plan */
4600 while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
4601 j++;
4602 }
4603
4604 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4605 do {
4606 if (i == MAX_CHANNEL_NUM ||
4607 chplan_sta[i].ChannelNum == 0)
4608 break;
4609
4610 if (j == chplan_ap.Len ||
4611 chplan_ap.Channel[j] == 0)
4612 break;
4613
4614 if (chplan_sta[i].ChannelNum ==
4615 chplan_ap.Channel[j]) {
4616 chplan_new[k].ChannelNum =
4617 chplan_ap.Channel[j];
4618 chplan_new[k].ScanType = SCAN_ACTIVE;
4619 i++;
4620 j++;
4621 k++;
4622 } else if (chplan_sta[i].ChannelNum <
4623 chplan_ap.Channel[j]) {
4624 chplan_new[k].ChannelNum =
4625 chplan_sta[i].ChannelNum;
4626 chplan_new[k].ScanType = SCAN_PASSIVE;
4627 i++;
4628 k++;
4629 } else if (chplan_sta[i].ChannelNum >
4630 chplan_ap.Channel[j]) {
4631 chplan_new[k].ChannelNum =
4632 chplan_ap.Channel[j];
4633 chplan_new[k].ScanType = SCAN_ACTIVE;
4634 j++;
4635 k++;
4636 }
4637 } while (1);
4638
4639 /* change AP not support channel to Passive scan */
4640 while (i < MAX_CHANNEL_NUM &&
4641 chplan_sta[i].ChannelNum != 0) {
4642 chplan_new[k].ChannelNum =
4643 chplan_sta[i].ChannelNum;
4644 chplan_new[k].ScanType = SCAN_PASSIVE;
4645 i++;
4646 k++;
4647 }
4648
4649 /* add channel AP supported */
4650 while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
4651 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4652 chplan_new[k].ScanType = SCAN_ACTIVE;
4653 j++;
4654 k++;
4655 }
4656 } else {
4657 /* keep original STA 5G channel plan */
4658 while (i < MAX_CHANNEL_NUM &&
4659 chplan_sta[i].ChannelNum != 0) {
4660 chplan_new[k].ChannelNum =
4661 chplan_sta[i].ChannelNum;
4662 chplan_new[k].ScanType = chplan_sta[i].ScanType;
4663 i++;
4664 k++;
4665 }
4666 }
4667 pmlmeext->update_channel_plan_by_ap_done = 1;
4668 }
4669
4670 /* If channel is used by AP, set channel scan type to active */
4671 channel = bssid->DSConfig;
4672 chplan_new = pmlmeext->channel_set;
4673 i = 0;
4674 while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
4675 if (chplan_new[i].ChannelNum == channel) {
4676 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4677 /* 5G Bnad 2, 3 (DFS) doesn't change
4678 to active scan */
4679 if (channel >= 52 && channel <= 144)
4680 break;
4681
4682 chplan_new[i].ScanType = SCAN_ACTIVE;
4683 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4684 "%s: change channel %d scan type from passive to active\n",
4685 __func__, channel);
4686 }
4687 break;
4688 }
4689 i++;
4690 }
4691 }
4692
4693 /****************************************************************************
4694
4695 Following are the functions to report events
4696
4697 *****************************************************************************/
4698
4699 void report_survey_event23a(struct rtw_adapter *padapter,
4700 struct recv_frame *precv_frame)
4701 {
4702 struct cmd_obj *pcmd_obj;
4703 u8 *pevtcmd;
4704 u32 cmdsz;
4705 struct survey_event *psurvey_evt;
4706 struct C2HEvent_Header *pc2h_evt_hdr;
4707 struct mlme_ext_priv *pmlmeext;
4708 struct cmd_priv *pcmdpriv;
4709
4710 if (!padapter)
4711 return;
4712
4713 pmlmeext = &padapter->mlmeextpriv;
4714 pcmdpriv = &padapter->cmdpriv;
4715
4716 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4717 if (!pcmd_obj)
4718 return;
4719
4720 cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
4721 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4722 if (!pevtcmd) {
4723 kfree(pcmd_obj);
4724 return;
4725 }
4726
4727 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4728 pcmd_obj->cmdsz = cmdsz;
4729 pcmd_obj->parmbuf = pevtcmd;
4730
4731 pcmd_obj->rsp = NULL;
4732 pcmd_obj->rspsz = 0;
4733
4734 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4735 pc2h_evt_hdr->len = sizeof(struct survey_event);
4736 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4737 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4738
4739 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4740
4741 psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
4742 if (!psurvey_evt->bss) {
4743 kfree(pcmd_obj);
4744 kfree(pevtcmd);
4745 return;
4746 }
4747
4748 process_80211d(padapter, psurvey_evt->bss);
4749
4750 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4751
4752 pmlmeext->sitesurvey_res.bss_cnt++;
4753 }
4754
4755 void report_surveydone_event23a(struct rtw_adapter *padapter)
4756 {
4757 struct cmd_obj *pcmd_obj;
4758 u8 *pevtcmd;
4759 u32 cmdsz;
4760 struct surveydone_event *psurveydone_evt;
4761 struct C2HEvent_Header *pc2h_evt_hdr;
4762 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4763 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4764
4765 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4766 if (!pcmd_obj)
4767 return;
4768
4769 cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
4770 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4771 if (!pevtcmd) {
4772 kfree(pcmd_obj);
4773 return;
4774 }
4775
4776 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4777 pcmd_obj->cmdsz = cmdsz;
4778 pcmd_obj->parmbuf = pevtcmd;
4779
4780 pcmd_obj->rsp = NULL;
4781 pcmd_obj->rspsz = 0;
4782
4783 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4784 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4785 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4786 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4787
4788 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4789 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4790
4791 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
4792
4793 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4794 }
4795
4796 void report_join_res23a(struct rtw_adapter *padapter, int res)
4797 {
4798 struct cmd_obj *pcmd_obj;
4799 u8 *pevtcmd;
4800 u32 cmdsz;
4801 struct joinbss_event *pjoinbss_evt;
4802 struct C2HEvent_Header *pc2h_evt_hdr;
4803 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4804 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4805 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4806
4807 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4808 if (!pcmd_obj)
4809 return;
4810
4811 cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
4812 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4813 if (!pevtcmd) {
4814 kfree(pcmd_obj);
4815 return;
4816 }
4817
4818 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4819 pcmd_obj->cmdsz = cmdsz;
4820 pcmd_obj->parmbuf = pevtcmd;
4821
4822 pcmd_obj->rsp = NULL;
4823 pcmd_obj->rspsz = 0;
4824
4825 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4826 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4827 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4828 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4829
4830 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4831 memcpy((unsigned char *)&pjoinbss_evt->network.network,
4832 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
4833 pjoinbss_evt->network.join_res = res;
4834
4835 DBG_8723A("report_join_res23a(%d)\n", res);
4836
4837 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
4838
4839 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4840 }
4841
4842 void report_del_sta_event23a(struct rtw_adapter *padapter,
4843 unsigned char *MacAddr, unsigned short reason)
4844 {
4845 struct cmd_obj *pcmd_obj;
4846 u8 *pevtcmd;
4847 u32 cmdsz;
4848 struct sta_info *psta;
4849 int mac_id;
4850 struct stadel_event *pdel_sta_evt;
4851 struct C2HEvent_Header *pc2h_evt_hdr;
4852 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4853 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4854
4855 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4856 if (!pcmd_obj)
4857 return;
4858
4859 cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
4860 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4861 if (!pevtcmd) {
4862 kfree(pcmd_obj);
4863 return;
4864 }
4865
4866 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4867 pcmd_obj->cmdsz = cmdsz;
4868 pcmd_obj->parmbuf = pevtcmd;
4869
4870 pcmd_obj->rsp = NULL;
4871 pcmd_obj->rspsz = 0;
4872
4873 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4874 pc2h_evt_hdr->len = sizeof(struct stadel_event);
4875 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4876 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4877
4878 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4879 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
4880 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
4881 2);
4882
4883 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
4884 if (psta)
4885 mac_id = (int)psta->mac_id;
4886 else
4887 mac_id = -1;
4888
4889 pdel_sta_evt->mac_id = mac_id;
4890
4891 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
4892
4893 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4894 }
4895
4896 void report_add_sta_event23a(struct rtw_adapter *padapter,
4897 unsigned char *MacAddr, int cam_idx)
4898 {
4899 struct cmd_obj *pcmd_obj;
4900 u8 *pevtcmd;
4901 u32 cmdsz;
4902 struct stassoc_event *padd_sta_evt;
4903 struct C2HEvent_Header *pc2h_evt_hdr;
4904 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4905 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4906
4907 pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
4908 if (!pcmd_obj)
4909 return;
4910
4911 cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
4912 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
4913 if (!pevtcmd) {
4914 kfree(pcmd_obj);
4915 return;
4916 }
4917
4918 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4919 pcmd_obj->cmdsz = cmdsz;
4920 pcmd_obj->parmbuf = pevtcmd;
4921
4922 pcmd_obj->rsp = NULL;
4923 pcmd_obj->rspsz = 0;
4924
4925 pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4926 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4927 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4928 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4929
4930 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
4931 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
4932 padd_sta_evt->cam_id = cam_idx;
4933
4934 DBG_8723A("report_add_sta_event23a: add STA\n");
4935
4936 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
4937 }
4938
4939 /****************************************************************************
4940
4941 Following are the event callback functions
4942
4943 *****************************************************************************/
4944
4945 /* for sta/adhoc mode */
4946 void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
4947 {
4948 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4949 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4950 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4951
4952 /* ERP */
4953 VCS_update23a(padapter, psta);
4954
4955 /* HT */
4956 if (pmlmepriv->htpriv.ht_option) {
4957 psta->htpriv.ht_option = true;
4958
4959 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4960
4961 if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
4962 psta->htpriv.sgi = true;
4963
4964 psta->qos_option = true;
4965
4966 } else {
4967 psta->htpriv.ht_option = false;
4968
4969 psta->htpriv.ampdu_enable = false;
4970
4971 psta->htpriv.sgi = false;
4972 psta->qos_option = false;
4973
4974 }
4975 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
4976 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4977
4978 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4979 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
4980
4981 /* QoS */
4982 if (pmlmepriv->qos_option)
4983 psta->qos_option = true;
4984
4985 psta->state = _FW_LINKED;
4986 }
4987
4988 void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
4989 int join_res)
4990 {
4991 struct sta_info *psta, *psta_bmc;
4992 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4993 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
4994 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
4995 struct sta_priv *pstapriv = &padapter->stapriv;
4996
4997 if (join_res < 0) {
4998 hw_var_set_mlme_join(padapter, 1);
4999 hw_var_set_bssid(padapter, null_addr);
5000
5001 /* restore to initial setting. */
5002 update_tx_basic_rate23a(padapter,
5003 padapter->registrypriv.wireless_mode);
5004
5005 goto exit_mlmeext_joinbss_event_callback23a;
5006 }
5007
5008 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
5009 /* for bc/mc */
5010 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
5011 if (psta_bmc) {
5012 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
5013 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
5014 Update_RA_Entry23a(padapter, psta_bmc);
5015 }
5016 }
5017
5018 /* turn on dynamic functions */
5019 rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
5020
5021 /* update IOT-releated issue */
5022 update_IOT_info23a(padapter);
5023
5024 HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
5025
5026 /* BCN interval */
5027 rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
5028
5029 /* update capability */
5030 update_capinfo23a(padapter, pmlmeinfo->capability);
5031
5032 /* WMM, Update EDCA param */
5033 WMMOnAssocRsp23a(padapter);
5034
5035 /* HT */
5036 HTOnAssocRsp23a(padapter);
5037
5038 /* Set cur_channel&cur_bwmode&cur_ch_offset */
5039 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5040
5041 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5042 if (psta) { /* only for infra. mode */
5043 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5044
5045 /* DBG_8723A("set_sta_rate23a\n"); */
5046
5047 psta->wireless_mode = pmlmeext->cur_wireless_mode;
5048
5049 /* set per sta rate after updating HT cap. */
5050 set_sta_rate23a(padapter, psta);
5051 }
5052
5053 hw_var_set_mlme_join(padapter, 2);
5054
5055 if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
5056 /* correcting TSF */
5057 rtw_correct_TSF(padapter);
5058
5059 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5060 }
5061
5062 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
5063
5064 exit_mlmeext_joinbss_event_callback23a:
5065 DBG_8723A("=>%s\n", __func__);
5066 }
5067
5068 void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
5069 struct sta_info *psta)
5070 {
5071 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5072 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5073
5074 DBG_8723A("%s\n", __func__);
5075
5076 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
5077 /* adhoc master or sta_count>1 */
5078 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5079 /* nothing to do */
5080 } else { /* adhoc client */
5081 /* correcting TSF */
5082 rtw_correct_TSF(padapter);
5083
5084 /* start beacon */
5085 if (send_beacon23a(padapter) != _SUCCESS) {
5086 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5087
5088 pmlmeinfo->state ^= MSR_ADHOC;
5089
5090 return;
5091 }
5092
5093 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5094 }
5095 hw_var_set_mlme_join(padapter, 2);
5096 }
5097
5098 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5099
5100 /* rate radaptive */
5101 Update_RA_Entry23a(padapter, psta);
5102
5103 /* update adhoc sta_info */
5104 update_sta_info23a(padapter, psta);
5105 }
5106
5107 void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
5108 {
5109 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5110 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5111
5112 if (is_client_associated_to_ap23a(padapter) ||
5113 is_IBSS_empty23a(padapter)) {
5114 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5115
5116 hw_var_set_mlme_disconnect(padapter);
5117 hw_var_set_bssid(padapter, null_addr);
5118
5119 /* restore to initial setting. */
5120 update_tx_basic_rate23a(padapter,
5121 padapter->registrypriv.wireless_mode);
5122
5123 /* switch to the 20M Hz mode after disconnect */
5124 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5125 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5126
5127 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5128 pmlmeext->cur_ch_offset,
5129 pmlmeext->cur_bwmode);
5130
5131 flush_all_cam_entry23a(padapter);
5132
5133 pmlmeinfo->state = MSR_NOLINK;
5134
5135 /* set MSR to no link state -> infra. mode */
5136 rtl8723a_set_media_status(padapter, MSR_INFRA);
5137
5138 del_timer_sync(&pmlmeext->link_timer);
5139 }
5140 }
5141
5142 static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
5143 {
5144 u8 ret = false;
5145
5146 if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
5147 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
5148 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
5149 ret = false;
5150 else
5151 ret = true;
5152
5153 sta_update_last_rx_pkts(psta);
5154 return ret;
5155 }
5156
5157 void linked_status_chk23a(struct rtw_adapter *padapter)
5158 {
5159 u32 i;
5160 struct sta_info *psta;
5161 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5162 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5163 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5164 struct sta_priv *pstapriv = &padapter->stapriv;
5165
5166 if (is_client_associated_to_ap23a(padapter)) {
5167 /* linked infrastructure client mode */
5168
5169 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5170 int rx_chk_limit;
5171
5172 rx_chk_limit = 4;
5173
5174 psta = rtw_get_stainfo23a(pstapriv,
5175 pmlmeinfo->network.MacAddress);
5176 if (psta) {
5177 bool is_p2p_enable = false;
5178
5179 if (chk_ap_is_alive(padapter, psta) == false)
5180 rx_chk = _FAIL;
5181
5182 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5183 tx_chk = _FAIL;
5184
5185 if (pmlmeext->active_keep_alive_check &&
5186 (rx_chk == _FAIL || tx_chk == _FAIL)) {
5187 u8 backup_oper_channel = 0;
5188
5189 /* switch to correct channel of current
5190 network before issue keep-alive frames */
5191 if (rtw_get_oper_ch23a(padapter) !=
5192 pmlmeext->cur_channel) {
5193 backup_oper_channel =
5194 rtw_get_oper_ch23a(padapter);
5195 SelectChannel23a(padapter,
5196 pmlmeext->cur_channel);
5197 }
5198
5199 if (rx_chk != _SUCCESS)
5200 issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
5201
5202 if ((tx_chk != _SUCCESS &&
5203 pmlmeinfo->link_count++ == 0xf) ||
5204 rx_chk != _SUCCESS) {
5205 tx_chk = issue_nulldata23a(padapter,
5206 psta->hwaddr,
5207 0, 3, 1);
5208 /* if tx acked and p2p disabled,
5209 set rx_chk _SUCCESS to reset retry
5210 count */
5211 if (tx_chk == _SUCCESS &&
5212 !is_p2p_enable)
5213 rx_chk = _SUCCESS;
5214 }
5215
5216 /* back to the original operation channel */
5217 if (backup_oper_channel>0)
5218 SelectChannel23a(padapter,
5219 backup_oper_channel);
5220 } else {
5221 if (rx_chk != _SUCCESS) {
5222 if (pmlmeext->retry == 0) {
5223 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5224 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5225 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
5226 }
5227 }
5228
5229 if (tx_chk != _SUCCESS &&
5230 pmlmeinfo->link_count++ == 0xf)
5231 tx_chk = issue_nulldata23a(padapter,
5232 NULL, 0, 1,
5233 0);
5234 }
5235
5236 if (rx_chk == _FAIL) {
5237 pmlmeext->retry++;
5238 if (pmlmeext->retry > rx_chk_limit) {
5239 DBG_8723A_LEVEL(_drv_always_,
5240 "%s(%s): disconnect or "
5241 "roaming\n", __func__,
5242 padapter->pnetdev->name);
5243 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
5244 WLAN_REASON_EXPIRATION_CHK);
5245 return;
5246 }
5247 } else
5248 pmlmeext->retry = 0;
5249
5250 if (tx_chk == _FAIL)
5251 pmlmeinfo->link_count &= 0xf;
5252 else {
5253 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5254 pmlmeinfo->link_count = 0;
5255 }
5256
5257 }
5258 } else if (is_client_associated_to_ibss23a(padapter)) {
5259 /* linked IBSS mode */
5260 /* for each assoc list entry to check the rx pkt counter */
5261 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5262 if (pmlmeinfo->FW_sta_info[i].status == 1) {
5263 psta = pmlmeinfo->FW_sta_info[i].psta;
5264
5265 if (!psta)
5266 continue;
5267
5268 if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
5269 sta_rx_pkts(psta)) {
5270
5271 if (pmlmeinfo->FW_sta_info[i].retry<3) {
5272 pmlmeinfo->FW_sta_info[i].retry++;
5273 } else {
5274 pmlmeinfo->FW_sta_info[i].retry = 0;
5275 pmlmeinfo->FW_sta_info[i].status = 0;
5276 report_del_sta_event23a(padapter, psta->hwaddr,
5277 65535/* indicate disconnect caused by no rx */
5278 );
5279 }
5280 } else {
5281 pmlmeinfo->FW_sta_info[i].retry = 0;
5282 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5283 }
5284 }
5285 }
5286 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5287 }
5288 }
5289
5290 static void survey_timer_hdl(unsigned long data)
5291 {
5292 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5293 struct cmd_obj *ph2c;
5294 struct sitesurvey_parm *psurveyPara;
5295 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5296 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5297
5298 /* issue rtw_sitesurvey_cmd23a */
5299 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5300 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
5301 pmlmeext->sitesurvey_res.channel_idx++;
5302
5303 if (pmlmeext->scan_abort == true) {
5304 pmlmeext->sitesurvey_res.channel_idx =
5305 pmlmeext->sitesurvey_res.ch_num;
5306 DBG_8723A("%s idx:%d\n", __func__,
5307 pmlmeext->sitesurvey_res.channel_idx);
5308
5309 pmlmeext->scan_abort = false;/* reset */
5310 }
5311
5312 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5313 if (!ph2c)
5314 goto exit_survey_timer_hdl;
5315
5316 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
5317 GFP_ATOMIC);
5318 if (!psurveyPara) {
5319 kfree(ph2c);
5320 goto exit_survey_timer_hdl;
5321 }
5322
5323 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
5324 GEN_CMD_CODE(_SiteSurvey));
5325 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
5326 }
5327
5328 exit_survey_timer_hdl:
5329 return;
5330 }
5331
5332 static void link_timer_hdl(unsigned long data)
5333 {
5334 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
5335 /* static unsigned int rx_pkt = 0; */
5336 /* static u64 tx_cnt = 0; */
5337 /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
5338 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5339 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5340 /* struct sta_priv *pstapriv = &padapter->stapriv; */
5341
5342 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5343 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
5344 pmlmeinfo->state = MSR_NOLINK;
5345 report_join_res23a(padapter, -3);
5346 } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5347 /* re-auth timer */
5348 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5349 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5350 /* */
5351 pmlmeinfo->state = 0;
5352 report_join_res23a(padapter, -1);
5353 return;
5354 /* */
5355 /* else */
5356 /* */
5357 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5358 /* pmlmeinfo->reauth_count = 0; */
5359 /* */
5360 }
5361
5362 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
5363 pmlmeinfo->auth_seq = 1;
5364 issue_auth(padapter, NULL, 0);
5365 set_link_timer(pmlmeext, REAUTH_TO);
5366 } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5367 /* re-assoc timer */
5368 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5369 pmlmeinfo->state = MSR_NOLINK;
5370 report_join_res23a(padapter, -2);
5371 return;
5372 }
5373
5374 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
5375 issue_assocreq(padapter);
5376 set_link_timer(pmlmeext, REASSOC_TO);
5377 }
5378 }
5379
5380 static void addba_timer_hdl(unsigned long data)
5381 {
5382 struct sta_info *psta = (struct sta_info *)data;
5383 struct ht_priv *phtpriv;
5384
5385 if (!psta)
5386 return;
5387
5388 phtpriv = &psta->htpriv;
5389
5390 if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5391 if (phtpriv->candidate_tid_bitmap)
5392 phtpriv->candidate_tid_bitmap = 0x0;
5393 }
5394 }
5395
5396 void init_addba_retry_timer23a(struct sta_info *psta)
5397 {
5398 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
5399 (unsigned long)psta);
5400 }
5401
5402 void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
5403 {
5404 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5405
5406 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
5407 (unsigned long)padapter);
5408
5409 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
5410 (unsigned long)padapter);
5411 }
5412
5413 int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5414 {
5415 return H2C_SUCCESS;
5416 }
5417
5418 int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5419 {
5420 enum nl80211_iftype type;
5421 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5422 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5423 const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5424
5425 switch (psetop->mode) {
5426 case NL80211_IFTYPE_P2P_GO:
5427 case NL80211_IFTYPE_AP:
5428 pmlmeinfo->state = MSR_AP;
5429 type = MSR_AP;
5430 break;
5431 case NL80211_IFTYPE_P2P_CLIENT:
5432 case NL80211_IFTYPE_STATION:
5433 /* clear state */
5434 pmlmeinfo->state &= ~(BIT(0)|BIT(1));
5435 /* set to STATION_STATE */
5436 pmlmeinfo->state |= MSR_INFRA;
5437 type = MSR_INFRA;
5438 break;
5439 case NL80211_IFTYPE_ADHOC:
5440 type = MSR_ADHOC;
5441 break;
5442 default:
5443 type = MSR_NOLINK;
5444 break;
5445 }
5446
5447 hw_var_set_opmode(padapter, type);
5448 /* Set_NETYPE0_MSR(padapter, type); */
5449
5450 return H2C_SUCCESS;
5451 }
5452
5453 int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5454 {
5455 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5456 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5457 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5458 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5459 /* u32 initialgain; */
5460
5461 if (pparm->ifmode == NL80211_IFTYPE_AP ||
5462 pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
5463 #ifdef CONFIG_8723AU_AP_MODE
5464 if (pmlmeinfo->state == MSR_AP) {
5465 /* todo: */
5466 return H2C_SUCCESS;
5467 }
5468 #endif
5469 }
5470
5471 /* below is for ad-hoc master */
5472 if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
5473 rtw_joinbss_reset23a(padapter);
5474
5475 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5476 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5477 pmlmeinfo->ERP_enable = 0;
5478 pmlmeinfo->WMM_enable = 0;
5479 pmlmeinfo->HT_enable = 0;
5480 pmlmeinfo->HT_caps_enable = 0;
5481 pmlmeinfo->HT_info_enable = 0;
5482
5483 /* disable dynamic functions, such as high power, DIG */
5484 rtl8723a_odm_support_ability_backup(padapter);
5485
5486 rtl8723a_odm_support_ability_clr(padapter,
5487 DYNAMIC_FUNC_DISABLE);
5488
5489 /* cancel link timer */
5490 del_timer_sync(&pmlmeext->link_timer);
5491
5492 /* clear CAM */
5493 flush_all_cam_entry23a(padapter);
5494
5495 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5496 return H2C_PARAMETERS_ERROR;
5497
5498 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
5499
5500 start_create_ibss(padapter);
5501 }
5502
5503 return H2C_SUCCESS;
5504 }
5505
5506 int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5507 {
5508 struct registry_priv *pregpriv = &padapter->registrypriv;
5509 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5510 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5511 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5512 const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
5513 struct ieee80211_ht_operation *pht_info;
5514 u32 i;
5515 u8 *p;
5516 /* u32 initialgain; */
5517 /* u32 acparm; */
5518
5519 /* check already connecting to AP or not */
5520 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5521 if (pmlmeinfo->state & MSR_INFRA)
5522 issue_deauth_ex(padapter, pnetwork->MacAddress,
5523 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
5524
5525 pmlmeinfo->state = MSR_NOLINK;
5526
5527 /* clear CAM */
5528 flush_all_cam_entry23a(padapter);
5529
5530 del_timer_sync(&pmlmeext->link_timer);
5531
5532 /* set MSR to nolink -> infra. mode */
5533 rtl8723a_set_media_status(padapter, MSR_INFRA);
5534
5535 hw_var_set_mlme_disconnect(padapter);
5536 }
5537
5538 rtw_joinbss_reset23a(padapter);
5539
5540 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5541 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5542 pmlmeinfo->ERP_enable = 0;
5543 pmlmeinfo->WMM_enable = 0;
5544 pmlmeinfo->HT_enable = 0;
5545 pmlmeinfo->HT_caps_enable = 0;
5546 pmlmeinfo->HT_info_enable = 0;
5547 pmlmeinfo->bwmode_updated = false;
5548 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5549
5550 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
5551 return H2C_PARAMETERS_ERROR;
5552
5553 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
5554
5555 /* Check AP vendor to move rtw_joinbss_cmd23a() */
5556 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
5557 pnetwork->IELength); */
5558
5559 for (i = 0; i < pnetwork->IELength;) {
5560 p = pnetwork->IEs + i;
5561
5562 switch (p[0]) {
5563 case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5564 if (!memcmp(p + 2, WMM_OUI23A, 4))
5565 pmlmeinfo->WMM_enable = 1;
5566 break;
5567
5568 case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
5569 pmlmeinfo->HT_caps_enable = 1;
5570 break;
5571
5572 case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
5573 pmlmeinfo->HT_info_enable = 1;
5574
5575 /* spec case only for cisco's ap because cisco's ap
5576 * issue assoc rsp using mcs rate @40MHz or @20MHz */
5577 pht_info = (struct ieee80211_ht_operation *)(p + 2);
5578
5579 if (pregpriv->cbw40_enable &&
5580 (pht_info->ht_param &
5581 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
5582 /* switch to the 40M Hz mode according to AP */
5583 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
5584 switch (pht_info->ht_param &
5585 IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
5586 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
5587 pmlmeext->cur_ch_offset =
5588 HAL_PRIME_CHNL_OFFSET_LOWER;
5589 break;
5590
5591 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
5592 pmlmeext->cur_ch_offset =
5593 HAL_PRIME_CHNL_OFFSET_UPPER;
5594 break;
5595
5596 default:
5597 pmlmeext->cur_ch_offset =
5598 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5599 break;
5600 }
5601
5602 DBG_8723A("set ch/bw before connected\n");
5603 }
5604 break;
5605
5606 default:
5607 break;
5608 }
5609
5610 i += (p[1] + 2);
5611 }
5612
5613 hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
5614 hw_var_set_mlme_join(padapter, 0);
5615
5616 /* cancel link timer */
5617 del_timer_sync(&pmlmeext->link_timer);
5618
5619 start_clnt_join(padapter);
5620
5621 return H2C_SUCCESS;
5622 }
5623
5624 int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5625 {
5626 const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5627 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5628 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5629 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
5630
5631 if (is_client_associated_to_ap23a(padapter)) {
5632 issue_deauth_ex(padapter, pnetwork->MacAddress,
5633 WLAN_REASON_DEAUTH_LEAVING,
5634 param->deauth_timeout_ms/100, 100);
5635 }
5636
5637 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5638
5639 /* pmlmeinfo->state = MSR_NOLINK; */
5640
5641 hw_var_set_mlme_disconnect(padapter);
5642 hw_var_set_bssid(padapter, null_addr);
5643
5644 /* restore to initial setting. */
5645 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
5646
5647 if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
5648 (pmlmeinfo->state & 0x03) == MSR_AP)
5649 rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */
5650
5651 /* set MSR to no link state -> infra. mode */
5652 rtl8723a_set_media_status(padapter, MSR_INFRA);
5653
5654 pmlmeinfo->state = MSR_NOLINK;
5655
5656 /* switch to the 20M Hz mode after disconnect */
5657 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
5658 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5659
5660 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
5661 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5662
5663 flush_all_cam_entry23a(padapter);
5664
5665 del_timer_sync(&pmlmeext->link_timer);
5666
5667 rtw_free_uc_swdec_pending_queue23a(padapter);
5668
5669 return H2C_SUCCESS;
5670 }
5671
5672 static int
5673 rtw_scan_ch_decision(struct rtw_adapter *padapter,
5674 struct rtw_ieee80211_channel *out, u32 out_num,
5675 const struct rtw_ieee80211_channel *in, u32 in_num)
5676 {
5677 int i, j;
5678 int scan_ch_num = 0;
5679 int set_idx;
5680 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5681
5682 /* clear out first */
5683 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5684
5685 /* acquire channels from in */
5686 j = 0;
5687 for (i = 0;i<in_num;i++) {
5688 if (in[i].hw_value &&
5689 !(in[i].flags & IEEE80211_CHAN_DISABLED) &&
5690 (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set,
5691 in[i].hw_value)) >= 0) {
5692 memcpy(&out[j], &in[i],
5693 sizeof(struct rtw_ieee80211_channel));
5694
5695 if (pmlmeext->channel_set[set_idx].ScanType ==
5696 SCAN_PASSIVE)
5697 out[j].flags &= IEEE80211_CHAN_NO_IR;
5698
5699 j++;
5700 }
5701 if (j>= out_num)
5702 break;
5703 }
5704
5705 /* if out is empty, use channel_set as default */
5706 if (j == 0) {
5707 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
5708 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
5709
5710 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5711 out[i].flags &= IEEE80211_CHAN_NO_IR;
5712
5713 j++;
5714 }
5715 }
5716
5717 if (padapter->setband == GHZ_24) { /* 2.4G */
5718 for (i = 0; i < j ; i++) {
5719 if (out[i].hw_value > 35)
5720 memset(&out[i], 0,
5721 sizeof(struct rtw_ieee80211_channel));
5722 else
5723 scan_ch_num++;
5724 }
5725 j = scan_ch_num;
5726 } else if (padapter->setband == GHZ_50) { /* 5G */
5727 for (i = 0; i < j ; i++) {
5728 if (out[i].hw_value > 35) {
5729 memcpy(&out[scan_ch_num++], &out[i],
5730 sizeof(struct rtw_ieee80211_channel));
5731 }
5732 }
5733 j = scan_ch_num;
5734 } else
5735 {}
5736
5737 return j;
5738 }
5739
5740 int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5741 {
5742 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5743 const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
5744 u8 bdelayscan = false;
5745 u32 initialgain;
5746 u32 i;
5747
5748 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5749 pmlmeext->sitesurvey_res.state = SCAN_START;
5750 pmlmeext->sitesurvey_res.bss_cnt = 0;
5751 pmlmeext->sitesurvey_res.channel_idx = 0;
5752
5753 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5754 if (pparm->ssid[i].ssid_len) {
5755 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
5756 pparm->ssid[i].ssid,
5757 IEEE80211_MAX_SSID_LEN);
5758 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
5759 pparm->ssid[i].ssid_len;
5760 } else {
5761 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
5762 }
5763 }
5764
5765 pmlmeext->sitesurvey_res.ch_num =
5766 rtw_scan_ch_decision(padapter,
5767 pmlmeext->sitesurvey_res.ch,
5768 RTW_CHANNEL_SCAN_AMOUNT,
5769 pparm->ch, pparm->ch_num);
5770
5771 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5772
5773 /* issue null data if associating to the AP */
5774 if (is_client_associated_to_ap23a(padapter)) {
5775 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5776
5777 /* switch to correct channel of current network
5778 before issue keep-alive frames */
5779 if (rtw_get_oper_ch23a(padapter) !=
5780 pmlmeext->cur_channel)
5781 SelectChannel23a(padapter,
5782 pmlmeext->cur_channel);
5783
5784 issue_nulldata23a(padapter, NULL, 1, 3, 500);
5785
5786 bdelayscan = true;
5787 }
5788
5789 if (bdelayscan) {
5790 /* delay 50ms to protect nulldata(1). */
5791 set_survey_timer(pmlmeext, 50);
5792 return H2C_SUCCESS;
5793 }
5794 }
5795
5796 if (pmlmeext->sitesurvey_res.state == SCAN_START ||
5797 pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
5798 /* disable dynamic functions, such as high power, DIG */
5799 rtl8723a_odm_support_ability_backup(padapter);
5800 rtl8723a_odm_support_ability_clr(padapter,
5801 DYNAMIC_FUNC_DISABLE);
5802
5803 /* config the initial gain under scanning, need to
5804 write the BB registers */
5805 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
5806 initialgain = 0x30;
5807 else
5808 initialgain = 0x1E;
5809
5810 rtl8723a_set_initial_gain(padapter, initialgain);
5811
5812 /* set MSR to no link state */
5813 rtl8723a_set_media_status(padapter, MSR_NOLINK);
5814
5815 rtl8723a_mlme_sitesurvey(padapter, 1);
5816
5817 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5818 }
5819
5820 rtw_site_survey(padapter);
5821
5822 return H2C_SUCCESS;
5823 }
5824
5825 int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5826 {
5827 const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
5828 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5829 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5830
5831 if (pparm->mode < 4)
5832 pmlmeinfo->auth_algo = pparm->mode;
5833
5834 return H2C_SUCCESS;
5835 }
5836
5837 int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5838 {
5839 unsigned short ctrl;
5840 const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
5841 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5842 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5843 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5844
5845 /* main tx key for wep. */
5846 if (pparm->set_tx)
5847 pmlmeinfo->key_index = pparm->keyid;
5848
5849 /* write cam */
5850 ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
5851
5852 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 "
5853 "WEP104-5 TKIP-2 AES-4) keyid:%d\n",
5854 pparm->algorithm, pparm->keyid);
5855 rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
5856
5857 /* allow multicast packets to driver */
5858 rtl8723a_on_rcr_am(padapter);
5859
5860 return H2C_SUCCESS;
5861 }
5862
5863 int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5864 {
5865 u16 ctrl = 0;
5866 u8 cam_id;/* cam_entry */
5867 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5868 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5869 const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
5870
5871 /* cam_entry: */
5872 /* 0~3 for default key */
5873
5874 /* for concurrent mode (ap+sta): */
5875 /* default key is disable, using sw encrypt/decrypt */
5876 /* cam_entry = 4 for sta mode (macid = 0) */
5877 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
5878
5879 /* for concurrent mode (sta+sta): */
5880 /* default key is disable, using sw encrypt/decrypt */
5881 /* cam_entry = 4 mapping to macid = 0 */
5882 /* cam_entry = 5 mapping to macid = 2 */
5883
5884 cam_id = 4;
5885
5886 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
5887 "WEP104-5 TKIP-2 AES-4) camid:%d\n",
5888 pparm->algorithm, cam_id);
5889 if ((pmlmeinfo->state & 0x03) == MSR_AP) {
5890 struct sta_info *psta;
5891 struct sta_priv *pstapriv = &padapter->stapriv;
5892
5893 if (pparm->algorithm == 0) { /* clear cam entry */
5894 clear_cam_entry23a(padapter, pparm->id);
5895 return H2C_SUCCESS_RSP;
5896 }
5897
5898 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
5899 if (psta) {
5900 ctrl = BIT(15) | (pparm->algorithm << 2);
5901
5902 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
5903 "=%d\n", pparm->algorithm);
5904
5905 if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) {
5906 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey"
5907 " failed, mac_id(aid) =%d\n",
5908 psta->mac_id);
5909 return H2C_REJECTED;
5910 }
5911
5912 /* 0~3 for default key, cmd_id = macid + 3,
5913 macid = aid+1; */
5914 cam_id = psta->mac_id + 3;
5915
5916 DBG_8723A("Write CAM, mac_addr =%pM, "
5917 "cam_entry =%d\n", pparm->addr, cam_id);
5918
5919 rtl8723a_cam_write(padapter, cam_id, ctrl,
5920 pparm->addr, pparm->key);
5921
5922 return H2C_SUCCESS_RSP;
5923 } else {
5924 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
5925 "free\n");
5926 return H2C_REJECTED;
5927 }
5928 }
5929
5930 /* below for sta mode */
5931
5932 if (pparm->algorithm == 0) { /* clear cam entry */
5933 clear_cam_entry23a(padapter, pparm->id);
5934 return H2C_SUCCESS;
5935 }
5936
5937 ctrl = BIT(15) | (pparm->algorithm << 2);
5938
5939 rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5940
5941 pmlmeinfo->enc_algo = pparm->algorithm;
5942
5943 return H2C_SUCCESS;
5944 }
5945
5946 int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
5947 {
5948 const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
5949 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5950 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5951 struct sta_info *psta;
5952
5953 psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
5954
5955 if (!psta)
5956 return H2C_SUCCESS;
5957
5958 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
5959 pmlmeinfo->HT_enable) ||
5960 (pmlmeinfo->state & 0x03) == MSR_AP) {
5961 issue_action_BA23a(padapter, pparm->addr,
5962 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5963 mod_timer(&psta->addba_retry_timer,
5964 jiffies + msecs_to_jiffies(ADDBA_TO));
5965 } else
5966 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5967
5968 return H2C_SUCCESS;
5969 }
5970
5971 int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
5972 {
5973 struct cmd_obj *ph2c;
5974 struct Tx_Beacon_param *ptxBeacon_parm;
5975 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5976 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5977 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5978 u8 res = _SUCCESS;
5979 int len_diff = 0;
5980
5981 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
5982 if (!ph2c) {
5983 res = _FAIL;
5984 goto exit;
5985 }
5986
5987 ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
5988 if (!ptxBeacon_parm) {
5989 kfree(ph2c);
5990 res = _FAIL;
5991 goto exit;
5992 }
5993
5994 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
5995 sizeof(struct wlan_bssid_ex));
5996
5997 len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
5998 ptxBeacon_parm->network.IELength,
5999 pmlmeinfo->hidden_ssid_mode);
6000 ptxBeacon_parm->network.IELength += len_diff;
6001
6002 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
6003 GEN_CMD_CODE(_TX_Beacon));
6004
6005 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
6006
6007 exit:
6008 return res;
6009 }
6010
6011 int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6012 {
6013 u8 evt_code, evt_seq;
6014 u16 evt_sz;
6015 const struct C2HEvent_Header *c2h;
6016 void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
6017
6018 c2h = (struct C2HEvent_Header *)pbuf;
6019 evt_sz = c2h->len;
6020 evt_seq = c2h->seq;
6021 evt_code = c2h->ID;
6022
6023 /* checking if event code is valid */
6024 if (evt_code >= MAX_C2HEVT) {
6025 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6026 "Event Code(%d) mismatch!\n", evt_code);
6027 goto _abort_event_;
6028 }
6029
6030 /* checking if event size match the event parm size */
6031 if (wlanevents[evt_code].parmsize != 0 &&
6032 wlanevents[evt_code].parmsize != evt_sz) {
6033 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
6034 "Event(%d) Parm Size mismatch (%d vs %d)!\n",
6035 evt_code, wlanevents[evt_code].parmsize, evt_sz);
6036 goto _abort_event_;
6037 }
6038
6039 event_callback = wlanevents[evt_code].event_callback;
6040 event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
6041
6042 _abort_event_:
6043
6044 return H2C_SUCCESS;
6045 }
6046
6047 int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6048 {
6049 if (!pbuf)
6050 return H2C_PARAMETERS_ERROR;
6051
6052 return H2C_SUCCESS;
6053 }
6054
6055 int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6056 {
6057 if (send_beacon23a(padapter) == _FAIL) {
6058 DBG_8723A("issue_beacon23a, fail!\n");
6059 return H2C_PARAMETERS_ERROR;
6060 }
6061 #ifdef CONFIG_8723AU_AP_MODE
6062 else { /* tx bc/mc frames after update TIM */
6063 struct sta_info *psta_bmc;
6064 struct list_head *phead;
6065 struct xmit_frame *pxmitframe, *ptmp;
6066 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6067 struct sta_priv *pstapriv = &padapter->stapriv;
6068
6069 /* for BC/MC Frames */
6070 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
6071 if (!psta_bmc)
6072 return H2C_SUCCESS;
6073
6074 if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
6075 msleep(10);/* 10ms, ATIM(HIQ) Windows */
6076 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6077 spin_lock_bh(&pxmitpriv->lock);
6078
6079 phead = get_list_head(&psta_bmc->sleep_q);
6080
6081 list_for_each_entry_safe(pxmitframe, ptmp,
6082 phead, list) {
6083
6084 list_del_init(&pxmitframe->list);
6085
6086 psta_bmc->sleepq_len--;
6087 if (psta_bmc->sleepq_len>0)
6088 pxmitframe->attrib.mdata = 1;
6089 else
6090 pxmitframe->attrib.mdata = 0;
6091
6092 pxmitframe->attrib.triggered = 1;
6093
6094 pxmitframe->attrib.qsel = 0x11;/* HIQ */
6095
6096 rtl8723au_hal_xmitframe_enqueue(padapter,
6097 pxmitframe);
6098 }
6099 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6100 spin_unlock_bh(&pxmitpriv->lock);
6101 }
6102 }
6103 #endif
6104
6105 return H2C_SUCCESS;
6106 }
6107
6108 int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6109 {
6110 const struct set_ch_parm *set_ch_parm;
6111 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6112
6113 if (!pbuf)
6114 return H2C_PARAMETERS_ERROR;
6115
6116 set_ch_parm = (struct set_ch_parm *)pbuf;
6117
6118 DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
6119 padapter->pnetdev->name, set_ch_parm->ch,
6120 set_ch_parm->bw, set_ch_parm->ch_offset);
6121
6122 pmlmeext->cur_channel = set_ch_parm->ch;
6123 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6124 pmlmeext->cur_bwmode = set_ch_parm->bw;
6125
6126 set_channel_bwmode23a(padapter, set_ch_parm->ch,
6127 set_ch_parm->ch_offset, set_ch_parm->bw);
6128
6129 return H2C_SUCCESS;
6130 }
6131
6132 int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6133 {
6134 const struct SetChannelPlan_param *setChannelPlan_param;
6135 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6136
6137 if (!pbuf)
6138 return H2C_PARAMETERS_ERROR;
6139
6140 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6141
6142 pmlmeext->max_chan_nums =
6143 init_channel_set(padapter, setChannelPlan_param->channel_plan,
6144 pmlmeext->channel_set);
6145 init_channel_list(padapter, pmlmeext->channel_set,
6146 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6147
6148 return H2C_SUCCESS;
6149 }
6150
6151 int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6152 {
6153 struct LedBlink_param *ledBlink_param;
6154
6155 if (!pbuf)
6156 return H2C_PARAMETERS_ERROR;
6157
6158 ledBlink_param = (struct LedBlink_param *)pbuf;
6159
6160 return H2C_SUCCESS;
6161 }
6162
6163 int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6164 {
6165 return H2C_REJECTED;
6166 }
6167
6168 /* TDLS_WRCR : write RCR DATA BIT */
6169 /* TDLS_SD_PTI : issue peer traffic indication */
6170 /* TDLS_CS_OFF : go back to the channel linked with AP,
6171 terminating channel switch procedure */
6172 /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and
6173 mgnt frame */
6174 /* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */
6175 /* TDLS_OFF_CH : first time set channel to off channel */
6176 /* TDLS_BASE_CH : go back tp the channel linked with AP when set
6177 base channel as target channel */
6178 /* TDLS_P_OFF_CH : periodically go to off channel */
6179 /* TDLS_P_BASE_CH : periodically go back to base channel */
6180 /* TDLS_RS_RCR : restore RCR */
6181 /* TDLS_CKALV_PH1 : check alive timer phase1 */
6182 /* TDLS_CKALV_PH2 : check alive timer phase2 */
6183 /* TDLS_FREE_STA : free tdls sta */
6184 int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
6185 {
6186 return H2C_REJECTED;
6187 }