Merge tag 'for-v3.13/clock-fixes-a' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / staging / rtl8188eu / 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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_MLME_EXT_C_
21
22 #include <osdep_service.h>
23 #include <drv_types.h>
24 #include <wifi.h>
25 #include <rtw_mlme_ext.h>
26 #include <wlan_bssdef.h>
27 #include <mlme_osdep.h>
28 #include <recv_osdep.h>
29
30 static struct mlme_handler mlme_sta_tbl[] = {
31         {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
32         {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
33         {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
34         {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
35         {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
36         {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
37
38         /*----------------------------------------------------------
39                                         below 2 are reserved
40         -----------------------------------------------------------*/
41         {0,                                     "DoReserved",           &DoReserved},
42         {0,                                     "DoReserved",           &DoReserved},
43         {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
44         {WIFI_ATIM,                     "OnATIM",               &OnAtim},
45         {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
46         {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
47         {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
48         {WIFI_ACTION,           "OnAction",             &OnAction},
49 };
50
51 static struct action_handler OnAction_tbl[] = {
52         {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
53         {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
54         {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
55         {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
56         {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
57         {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
58         {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
59         {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
60         {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
61         {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
62         {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
63 };
64
65
66 static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
67
68 /**************************************************
69 OUI definitions for the vendor specific IE
70 ***************************************************/
71 unsigned char   RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
72 unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
73 unsigned char   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
74 unsigned char   P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
75 unsigned char   WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
76
77 unsigned char   WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
78 unsigned char   WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
79
80 unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
81 unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
82
83 extern unsigned char REALTEK_96B_IE[];
84
85 /********************************************************
86 MCS rate definitions
87 *********************************************************/
88 unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
89 unsigned char   MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
90
91 /********************************************************
92 ChannelPlan definitions
93 *********************************************************/
94 static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
95         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
96         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
97         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
98         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
99         {{10, 11, 12, 13}, 4},                                  /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
100         {{}, 0},                                                                        /*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
101 };
102
103 static struct rt_channel_plan_map       RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
104         /*  0x00 ~ 0x1F , Old Define ===== */
105         {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
106         {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
107         {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
108         {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
109         {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
110         {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
111         {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
112         {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
113         {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
114         {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
115         {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
116         {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
117         {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
118         {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
119         {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
120         {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
121         {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
122         {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
123         {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
124         {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
125         {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
126         {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
127         {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
128         {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
129         {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
130         {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
131         {0x00}, /* 0x1A, */
132         {0x00}, /* 0x1B, */
133         {0x00}, /* 0x1C, */
134         {0x00}, /* 0x1D, */
135         {0x00}, /* 0x1E, */
136         {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
137         /*  0x20 ~ 0x7F , New Define ===== */
138         {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
139         {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
140         {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
141         {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
142         {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
143         {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
144         {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
145         {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
146         {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
147         {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
148         {0x00}, /* 0x2A, */
149         {0x00}, /* 0x2B, */
150         {0x00}, /* 0x2C, */
151         {0x00}, /* 0x2D, */
152         {0x00}, /* 0x2E, */
153         {0x00}, /* 0x2F, */
154         {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
155         {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
156         {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
157         {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
158         {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
159         {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
160         {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
161         {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
162         {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
163         {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
164         {0x00}, /* 0x3A, */
165         {0x00}, /* 0x3B, */
166         {0x00}, /* 0x3C, */
167         {0x00}, /* 0x3D, */
168         {0x00}, /* 0x3E, */
169         {0x00}, /* 0x3F, */
170         {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
171         {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
172 };
173
174 static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
175
176 /*
177  * Search the @param channel_num in given @param channel_set
178  * @ch_set: the given channel set
179  * @ch: the given channel number
180  *
181  * return the index of channel_num in channel_set, -1 if not found
182  */
183 int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
184 {
185         int i;
186         for (i = 0; ch_set[i].ChannelNum != 0; i++) {
187                 if (ch == ch_set[i].ChannelNum)
188                         break;
189         }
190
191         if (i >= ch_set[i].ChannelNum)
192                 return -1;
193         return i;
194 }
195
196 /****************************************************************************
197
198 Following are the initialization functions for WiFi MLME
199
200 *****************************************************************************/
201
202 int init_hw_mlme_ext(struct adapter *padapter)
203 {
204         struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
205
206         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
207         return _SUCCESS;
208 }
209
210 static void init_mlme_ext_priv_value(struct adapter *padapter)
211 {
212         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
213         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
214         unsigned char   mixed_datarate[NumRates] = {
215                 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
216                 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
217                  _48M_RATE_, _54M_RATE_, 0xff
218         };
219         unsigned char   mixed_basicrate[NumRates] = {
220                 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
221                 _12M_RATE_, _24M_RATE_, 0xff,
222         };
223
224         ATOMIC_SET(&pmlmeext->event_seq, 0);
225         pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
226
227         pmlmeext->cur_channel = padapter->registrypriv.channel;
228         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
229         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
230         pmlmeext->oper_channel = pmlmeext->cur_channel ;
231         pmlmeext->oper_bwmode = pmlmeext->cur_bwmode;
232         pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset;
233         pmlmeext->retry = 0;
234
235         pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
236
237         memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
238         memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
239
240         pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
241
242         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
243         pmlmeext->sitesurvey_res.channel_idx = 0;
244         pmlmeext->sitesurvey_res.bss_cnt = 0;
245         pmlmeext->scan_abort = false;
246
247         pmlmeinfo->state = WIFI_FW_NULL_STATE;
248         pmlmeinfo->reauth_count = 0;
249         pmlmeinfo->reassoc_count = 0;
250         pmlmeinfo->link_count = 0;
251         pmlmeinfo->auth_seq = 0;
252         pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
253         pmlmeinfo->key_index = 0;
254         pmlmeinfo->iv = 0;
255
256         pmlmeinfo->enc_algo = _NO_PRIVACY_;
257         pmlmeinfo->authModeToggle = 0;
258
259         _rtw_memset(pmlmeinfo->chg_txt, 0, 128);
260
261         pmlmeinfo->slotTime = SHORT_SLOT_TIME;
262         pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
263
264         pmlmeinfo->dialogToken = 0;
265
266         pmlmeext->action_public_rxseq = 0xffff;
267         pmlmeext->action_public_dialog_token = 0xff;
268 }
269
270 static int has_channel(struct rt_channel_info *channel_set,
271                                            u8 chanset_size,
272                                            u8 chan) {
273         int i;
274
275         for (i = 0; i < chanset_size; i++) {
276                 if (channel_set[i].ChannelNum == chan)
277                         return 1;
278         }
279         return 0;
280 }
281
282 static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
283                                                           u8 chanset_size,
284                                                           struct p2p_channels *channel_list) {
285         struct p2p_oper_class_map op_class[] = {
286                 { IEEE80211G,  81,   1,  13,  1, BW20 },
287                 { IEEE80211G,  82,  14,  14,  1, BW20 },
288                 { -1, 0, 0, 0, 0, BW20 }
289         };
290
291         int cla, op;
292
293         cla = 0;
294
295         for (op = 0; op_class[op].op_class; op++) {
296                 u8 ch;
297                 struct p2p_oper_class_map *o = &op_class[op];
298                 struct p2p_reg_class *reg = NULL;
299
300                 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
301                         if (!has_channel(channel_set, chanset_size, ch)) {
302                                 continue;
303                         }
304
305                         if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
306                                 continue;
307
308                         if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
309                             ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
310                                 continue;
311
312                         if (reg == NULL) {
313                                 reg = &channel_list->reg_class[cla];
314                                 cla++;
315                                 reg->reg_class = o->op_class;
316                                 reg->channels = 0;
317                         }
318                         reg->channel[reg->channels] = ch;
319                         reg->channels++;
320                 }
321         }
322         channel_list->reg_classes = cla;
323 }
324
325 static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
326 {
327         u8 index, chanset_size = 0;
328         u8 b2_4GBand = false;
329         u8 Index2G = 0;
330
331         _rtw_memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
332
333         if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
334                 DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
335                 return chanset_size;
336         }
337
338         if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
339                 b2_4GBand = true;
340                 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
341                         Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
342                 else
343                         Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
344         }
345
346         if (b2_4GBand) {
347                 for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
348                         channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
349
350                         if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
351                             (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)) {
352                                 if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
353                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
354                                 else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
355                                         channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
356                         } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
357                                    RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {/*  channel 12~13, passive scan */
358                                 if (channel_set[chanset_size].ChannelNum <= 11)
359                                         channel_set[chanset_size].ScanType = SCAN_ACTIVE;
360                                 else
361                                         channel_set[chanset_size].ScanType = SCAN_PASSIVE;
362                         } else {
363                                 channel_set[chanset_size].ScanType = SCAN_ACTIVE;
364                         }
365
366                         chanset_size++;
367                 }
368         }
369         return chanset_size;
370 }
371
372 int     init_mlme_ext_priv(struct adapter *padapter)
373 {
374         int     res = _SUCCESS;
375         struct registry_priv *pregistrypriv = &padapter->registrypriv;
376         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
377         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
378         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
379
380         pmlmeext->padapter = padapter;
381
382         init_mlme_ext_priv_value(padapter);
383         pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
384
385         init_mlme_ext_timer(padapter);
386
387 #ifdef CONFIG_88EU_AP_MODE
388         init_mlme_ap_info(padapter);
389 #endif
390
391         pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
392         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
393
394         pmlmeext->chan_scan_time = SURVEY_TO;
395         pmlmeext->mlmeext_init = true;
396
397
398         pmlmeext->active_keep_alive_check = true;
399
400         return res;
401 }
402
403 void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
404 {
405         struct adapter *padapter = pmlmeext->padapter;
406
407         if (!padapter)
408                 return;
409
410         if (padapter->bDriverStopped) {
411                 _cancel_timer_ex(&pmlmeext->survey_timer);
412                 _cancel_timer_ex(&pmlmeext->link_timer);
413                 /* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
414         }
415 }
416
417 static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
418 {
419         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
420         u8 *pframe = precv_frame->u.hdr.rx_data;
421
422           if (ptable->func) {
423          /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
424                 if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
425                     !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
426                         return;
427                 ptable->func(padapter, precv_frame);
428         }
429 }
430
431 void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
432 {
433         int index;
434         struct mlme_handler *ptable;
435 #ifdef CONFIG_88EU_AP_MODE
436         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
437 #endif /* CONFIG_88EU_AP_MODE */
438         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
439         u8 *pframe = precv_frame->u.hdr.rx_data;
440         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
441
442         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
443                  ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
444                   GetFrameType(pframe), GetFrameSubType(pframe)));
445
446         if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
447                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
448                 return;
449         }
450
451         /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
452         if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
453             !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
454                 return;
455
456         ptable = mlme_sta_tbl;
457
458         index = GetFrameSubType(pframe) >> 4;
459
460         if (index > 13) {
461                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index));
462                 return;
463         }
464         ptable += index;
465
466         if (psta != NULL) {
467                 if (GetRetry(pframe)) {
468                         if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
469                                 /* drop the duplicate management frame */
470                                 DBG_88E("Drop duplicate management frame with seq_num=%d.\n", precv_frame->u.hdr.attrib.seq_num);
471                                 return;
472                         }
473                 }
474                 psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
475         }
476
477 #ifdef CONFIG_88EU_AP_MODE
478         switch (GetFrameSubType(pframe)) {
479         case WIFI_AUTH:
480                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
481                         ptable->func = &OnAuth;
482                 else
483                         ptable->func = &OnAuthClient;
484                 /* fall through */
485         case WIFI_ASSOCREQ:
486         case WIFI_REASSOCREQ:
487                 _mgt_dispatcher(padapter, ptable, precv_frame);
488                 break;
489         case WIFI_PROBEREQ:
490                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
491                         _mgt_dispatcher(padapter, ptable, precv_frame);
492                 else
493                         _mgt_dispatcher(padapter, ptable, precv_frame);
494                 break;
495         case WIFI_BEACON:
496                 _mgt_dispatcher(padapter, ptable, precv_frame);
497                 break;
498         case WIFI_ACTION:
499                 _mgt_dispatcher(padapter, ptable, precv_frame);
500                 break;
501         default:
502                 _mgt_dispatcher(padapter, ptable, precv_frame);
503                 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
504                         rtw_hostapd_mlme_rx(padapter, precv_frame);
505                 break;
506         }
507 #else
508         _mgt_dispatcher(padapter, ptable, precv_frame);
509 #endif
510 }
511
512 #ifdef CONFIG_88EU_P2P
513 static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da)
514 {
515         bool response = true;
516
517         /*      do nothing if the device name is empty */
518         if (!padapter->wdinfo.device_name_len)
519                 response = false;
520
521         if (response)
522                 issue_probersp_p2p(padapter, da);
523
524         return _SUCCESS;
525 }
526 #endif /* CONFIG_88EU_P2P */
527
528
529 /****************************************************************************
530
531 Following are the callback functions for each subtype of the management frames
532
533 *****************************************************************************/
534
535 unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
536 {
537         unsigned int    ielen;
538         unsigned char   *p;
539         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
540         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
541         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
542         struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
543         u8 *pframe = precv_frame->u.hdr.rx_data;
544         uint len = precv_frame->u.hdr.len;
545         u8 is_valid_p2p_probereq = false;
546
547 #ifdef CONFIG_88EU_P2P
548         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
549         u8 wifi_test_chk_rate = 1;
550
551         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
552             !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
553             !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
554             !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
555             !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
556                 /*      mcs_rate = 0 -> CCK 1M rate */
557                 /*      mcs_rate = 1 -> CCK 2M rate */
558                 /*      mcs_rate = 2 -> CCK 5.5M rate */
559                 /*      mcs_rate = 3 -> CCK 11M rate */
560                 /*      In the P2P mode, the driver should not support the CCK rate */
561
562                 /*      Commented by Kurt 2012/10/16 */
563                 /*      IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
564                 if (wifi_test_chk_rate == 1) {
565                         is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
566                         if (is_valid_p2p_probereq) {
567                                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
568                                         /*  FIXME */
569                                         report_survey_event(padapter, precv_frame);
570                                         p2p_listen_state_process(padapter,  get_sa(pframe));
571
572                                         return _SUCCESS;
573                                 }
574
575                                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
576                                         goto _continue;
577                         }
578                 }
579         }
580
581 _continue:
582 #endif /* CONFIG_88EU_P2P */
583
584         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
585                 return _SUCCESS;
586
587         if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
588             !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
589                 return _SUCCESS;
590
591         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
592                         len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
593
594         /* check (wildcard) SSID */
595         if (p != NULL) {
596                 if (is_valid_p2p_probereq)
597                         goto _issue_probersp;
598
599                 if ((ielen != 0 && !_rtw_memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
600                     (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
601                         return _SUCCESS;
602
603 _issue_probersp:
604
605                 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
606                     pmlmepriv->cur_network.join_res)
607                         issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
608         }
609         return _SUCCESS;
610 }
611
612 unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
613 {
614         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
615 #ifdef CONFIG_88EU_P2P
616         struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
617         u8 *pframe = precv_frame->u.hdr.rx_data;
618 #endif
619
620 #ifdef CONFIG_88EU_P2P
621         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
622                 if (pwdinfo->tx_prov_disc_info.benable) {
623                         if (_rtw_memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
624                                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
625                                         pwdinfo->tx_prov_disc_info.benable = false;
626                                         issue_p2p_provision_request(padapter,
627                                                                     pwdinfo->tx_prov_disc_info.ssid.Ssid,
628                                                                     pwdinfo->tx_prov_disc_info.ssid.SsidLength,
629                                                                     pwdinfo->tx_prov_disc_info.peerDevAddr);
630                                 } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
631                                         pwdinfo->tx_prov_disc_info.benable = false;
632                                         issue_p2p_provision_request(padapter, NULL, 0,
633                                                                     pwdinfo->tx_prov_disc_info.peerDevAddr);
634                                 }
635                         }
636                 }
637                 return _SUCCESS;
638         } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
639                 if (pwdinfo->nego_req_info.benable) {
640                         DBG_88E("[%s] P2P State is GONEGO ING!\n", __func__);
641                         if (_rtw_memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
642                                 pwdinfo->nego_req_info.benable = false;
643                                 issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
644                         }
645                 }
646         } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
647                 if (pwdinfo->invitereq_info.benable) {
648                         DBG_88E("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
649                         if (_rtw_memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
650                                 pwdinfo->invitereq_info.benable = false;
651                                 issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
652                         }
653                 }
654         }
655 #endif
656
657
658         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
659                 report_survey_event(padapter, precv_frame);
660                 return _SUCCESS;
661         }
662
663         return _SUCCESS;
664 }
665
666 unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
667 {
668         int cam_idx;
669         struct sta_info *psta;
670         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
671         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
672         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
673         struct sta_priv *pstapriv = &padapter->stapriv;
674         u8 *pframe = precv_frame->u.hdr.rx_data;
675         uint len = precv_frame->u.hdr.len;
676         struct wlan_bssid_ex *pbss;
677         int ret = _SUCCESS;
678
679         if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
680                 report_survey_event(padapter, precv_frame);
681                 return _SUCCESS;
682         }
683
684         if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
685                 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
686                         /* we should update current network before auth, or some IE is wrong */
687                         pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
688                         if (pbss) {
689                                 if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
690                                         update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
691                                         rtw_get_bcn_info(&(pmlmepriv->cur_network));
692                                 }
693                                 kfree(pbss);
694                         }
695
696                         /* check the vendor of the assoc AP */
697                         pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr));
698
699                         /* update TSF Value */
700                         update_TSF(pmlmeext, pframe, len);
701
702                         /* start auth */
703                         start_clnt_auth(padapter);
704
705                         return _SUCCESS;
706                 }
707
708                 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
709                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
710                         if (psta != NULL) {
711                                 ret = rtw_check_bcn_info(padapter, pframe, len);
712                                 if (!ret) {
713                                                 DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n ");
714                                                 receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535);
715                                                 return _SUCCESS;
716                                 }
717                                 /* update WMM, ERP in the beacon */
718                                 /* todo: the timer is used instead of the number of the beacon received */
719                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
720                                         update_beacon_info(padapter, pframe, len, psta);
721                                 process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
722                         }
723                 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
724                         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
725                         if (psta != NULL) {
726                                 /* update WMM, ERP in the beacon */
727                                 /* todo: the timer is used instead of the number of the beacon received */
728                                 if ((sta_rx_pkts(psta) & 0xf) == 0)
729                                         update_beacon_info(padapter, pframe, len, psta);
730                         } else {
731                                 /* allocate a new CAM entry for IBSS station */
732                                 cam_idx = allocate_fw_sta_entry(padapter);
733                                 if (cam_idx == NUM_STA)
734                                         goto _END_ONBEACON_;
735
736                                 /* get supported rate */
737                                 if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
738                                         pmlmeinfo->FW_sta_info[cam_idx].status = 0;
739                                         goto _END_ONBEACON_;
740                                 }
741
742                                 /* update TSF Value */
743                                 update_TSF(pmlmeext, pframe, len);
744
745                                 /* report sta add event */
746                                 report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
747                         }
748                 }
749         }
750
751 _END_ONBEACON_:
752
753         return _SUCCESS;
754 }
755
756 unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
757 {
758 #ifdef CONFIG_88EU_AP_MODE
759         unsigned long irqL;
760         unsigned int    auth_mode, ie_len;
761         u16 seq;
762         unsigned char   *sa, *p;
763         u16 algorithm;
764         int     status;
765         static struct sta_info stat;
766         struct  sta_info        *pstat = NULL;
767         struct  sta_priv *pstapriv = &padapter->stapriv;
768         struct security_priv *psecuritypriv = &padapter->securitypriv;
769         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
770         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
771         u8 *pframe = precv_frame->u.hdr.rx_data;
772         uint len = precv_frame->u.hdr.len;
773
774         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
775                 return _FAIL;
776
777         DBG_88E("+OnAuth\n");
778
779         sa = GetAddr2Ptr(pframe);
780
781         auth_mode = psecuritypriv->dot11AuthAlgrthm;
782         seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
783         algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
784
785         DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq);
786
787         if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
788             psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
789                 auth_mode = 0;
790
791         if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
792             (algorithm == 0 && auth_mode == 1)) {       /*  rx a open-system auth but shared-key is enabled */
793                 DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
794                         algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
795
796                 status = _STATS_NO_SUPP_ALG_;
797
798                 goto auth_fail;
799         }
800
801         if (!rtw_access_ctrl(padapter, sa)) {
802                 status = _STATS_UNABLE_HANDLE_STA_;
803                 goto auth_fail;
804         }
805
806         pstat = rtw_get_stainfo(pstapriv, sa);
807         if (pstat == NULL) {
808                 /*  allocate a new one */
809                 DBG_88E("going to alloc stainfo for sa=%pM\n", sa);
810                 pstat = rtw_alloc_stainfo(pstapriv, sa);
811                 if (pstat == NULL) {
812                         DBG_88E(" Exceed the upper limit of supported clients...\n");
813                         status = _STATS_UNABLE_HANDLE_STA_;
814                         goto auth_fail;
815                 }
816
817                 pstat->state = WIFI_FW_AUTH_NULL;
818                 pstat->auth_seq = 0;
819         } else {
820                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
821                 if (!rtw_is_list_empty(&pstat->asoc_list)) {
822                         rtw_list_delete(&pstat->asoc_list);
823                         pstapriv->asoc_list_cnt--;
824                 }
825                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
826
827                 if (seq == 1) {
828                         /* TODO: STA re_auth and auth timeout */
829                 }
830         }
831
832         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
833         if (rtw_is_list_empty(&pstat->auth_list)) {
834                 rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
835                 pstapriv->auth_list_cnt++;
836         }
837         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
838
839         if (pstat->auth_seq == 0)
840                 pstat->expire_to = pstapriv->auth_to;
841
842         if ((pstat->auth_seq + 1) != seq) {
843                 DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
844                         seq, pstat->auth_seq+1);
845                 status = _STATS_OUT_OF_AUTH_SEQ_;
846                 goto auth_fail;
847         }
848
849         if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
850                 if (seq == 1) {
851                         pstat->state &= ~WIFI_FW_AUTH_NULL;
852                         pstat->state |= WIFI_FW_AUTH_SUCCESS;
853                         pstat->expire_to = pstapriv->assoc_to;
854                         pstat->authalg = algorithm;
855                 } else {
856                         DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
857                                 seq, pstat->auth_seq+1);
858                         status = _STATS_OUT_OF_AUTH_SEQ_;
859                         goto auth_fail;
860                 }
861         } else { /*  shared system or auto authentication */
862                 if (seq == 1) {
863                         /* prepare for the challenging txt... */
864
865                         pstat->state &= ~WIFI_FW_AUTH_NULL;
866                         pstat->state |= WIFI_FW_AUTH_STATE;
867                         pstat->authalg = algorithm;
868                         pstat->auth_seq = 2;
869                 } else if (seq == 3) {
870                         /* checking for challenging txt... */
871                         DBG_88E("checking for challenging txt...\n");
872
873                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
874                                         len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
875
876                         if ((p == NULL) || (ie_len <= 0)) {
877                                 DBG_88E("auth rejected because challenge failure!(1)\n");
878                                 status = _STATS_CHALLENGE_FAIL_;
879                                 goto auth_fail;
880                         }
881
882                         if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
883                                 pstat->state &= (~WIFI_FW_AUTH_STATE);
884                                 pstat->state |= WIFI_FW_AUTH_SUCCESS;
885                                 /*  challenging txt is correct... */
886                                 pstat->expire_to =  pstapriv->assoc_to;
887                         } else {
888                                 DBG_88E("auth rejected because challenge failure!\n");
889                                 status = _STATS_CHALLENGE_FAIL_;
890                                 goto auth_fail;
891                         }
892                 } else {
893                         DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
894                                 seq, pstat->auth_seq+1);
895                         status = _STATS_OUT_OF_AUTH_SEQ_;
896                         goto auth_fail;
897                 }
898         }
899
900         /*  Now, we are going to issue_auth... */
901         pstat->auth_seq = seq + 1;
902
903 #ifdef CONFIG_88EU_AP_MODE
904         issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
905 #endif
906
907         if (pstat->state & WIFI_FW_AUTH_SUCCESS)
908                 pstat->auth_seq = 0;
909
910         return _SUCCESS;
911
912 auth_fail:
913
914         if (pstat)
915                 rtw_free_stainfo(padapter , pstat);
916
917         pstat = &stat;
918         _rtw_memset((char *)pstat, '\0', sizeof(stat));
919         pstat->auth_seq = 2;
920         memcpy(pstat->hwaddr, sa, 6);
921
922 #ifdef CONFIG_88EU_AP_MODE
923         issue_auth(padapter, pstat, (unsigned short)status);
924 #endif
925
926 #endif
927         return _FAIL;
928 }
929
930 unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
931 {
932         unsigned int    seq, len, status, offset;
933         unsigned char   *p;
934         unsigned int    go2asoc = 0;
935         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
936         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
937         u8 *pframe = precv_frame->u.hdr.rx_data;
938         uint pkt_len = precv_frame->u.hdr.len;
939
940         DBG_88E("%s\n", __func__);
941
942         /* check A1 matches or not */
943         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
944                 return _SUCCESS;
945
946         if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
947                 return _SUCCESS;
948
949         offset = (GetPrivacy(pframe)) ? 4 : 0;
950
951         seq     = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
952         status  = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
953
954         if (status != 0) {
955                 DBG_88E("clnt auth fail, status: %d\n", status);
956                 if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
957                         if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
958                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
959                         else
960                                 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
961                 }
962
963                 set_link_timer(pmlmeext, 1);
964                 goto authclnt_fail;
965         }
966
967         if (seq == 2) {
968                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
969                          /*  legendary shared system */
970                         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
971                                 pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
972
973                         if (p == NULL)
974                                 goto authclnt_fail;
975
976                         memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
977                         pmlmeinfo->auth_seq = 3;
978                         issue_auth(padapter, NULL, 0);
979                         set_link_timer(pmlmeext, REAUTH_TO);
980
981                         return _SUCCESS;
982                 } else {
983                         /*  open system */
984                         go2asoc = 1;
985                 }
986         } else if (seq == 4) {
987                 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
988                         go2asoc = 1;
989                 else
990                         goto authclnt_fail;
991         } else {
992                 /*  this is also illegal */
993                 goto authclnt_fail;
994         }
995
996         if (go2asoc) {
997                 DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n");
998                 start_clnt_assoc(padapter);
999                 return _SUCCESS;
1000         }
1001 authclnt_fail:
1002         return _FAIL;
1003 }
1004
1005 unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
1006 {
1007 #ifdef CONFIG_88EU_AP_MODE
1008         unsigned long irqL;
1009         u16 capab_info;
1010         struct rtw_ieee802_11_elems elems;
1011         struct sta_info *pstat;
1012         unsigned char           reassoc, *p, *pos, *wpa_ie;
1013         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1014         int             i, ie_len, wpa_ie_len, left;
1015         unsigned char           supportRate[16];
1016         int                                     supportRateNum;
1017         unsigned short          status = _STATS_SUCCESSFUL_;
1018         unsigned short          frame_type, ie_offset = 0;
1019         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1020         struct security_priv *psecuritypriv = &padapter->securitypriv;
1021         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1022         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1023         struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
1024         struct sta_priv *pstapriv = &padapter->stapriv;
1025         u8 *pframe = precv_frame->u.hdr.rx_data;
1026         uint pkt_len = precv_frame->u.hdr.len;
1027 #ifdef CONFIG_88EU_P2P
1028         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
1029         u8 p2p_status_code = P2P_STATUS_SUCCESS;
1030         u8 *p2pie;
1031         u32 p2pielen = 0;
1032 #endif /* CONFIG_88EU_P2P */
1033
1034         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1035                 return _FAIL;
1036
1037         frame_type = GetFrameSubType(pframe);
1038         if (frame_type == WIFI_ASSOCREQ) {
1039                 reassoc = 0;
1040                 ie_offset = _ASOCREQ_IE_OFFSET_;
1041         } else { /*  WIFI_REASSOCREQ */
1042                 reassoc = 1;
1043                 ie_offset = _REASOCREQ_IE_OFFSET_;
1044         }
1045
1046
1047         if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
1048                 DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
1049                        "\n", reassoc, (unsigned long)pkt_len);
1050                 return _FAIL;
1051         }
1052
1053         pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1054         if (pstat == (struct sta_info *)NULL) {
1055                 status = _RSON_CLS2_;
1056                 goto asoc_class2_error;
1057         }
1058
1059         capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
1060
1061         left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1062         pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1063
1064
1065         DBG_88E("%s\n", __func__);
1066
1067         /*  check if this stat has been successfully authenticated/assocated */
1068         if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
1069                 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
1070                         status = _RSON_CLS2_;
1071                         goto asoc_class2_error;
1072                 } else {
1073                         pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1074                         pstat->state |= WIFI_FW_ASSOC_STATE;
1075                 }
1076         } else {
1077                 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1078                 pstat->state |= WIFI_FW_ASSOC_STATE;
1079         }
1080         pstat->capability = capab_info;
1081         /* now parse all ieee802_11 ie to point to elems */
1082         if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1083             !elems.ssid) {
1084                 DBG_88E("STA %pM sent invalid association request\n",
1085                         pstat->hwaddr);
1086                 status = _STATS_FAILURE_;
1087                 goto OnAssocReqFail;
1088         }
1089
1090
1091         /*  now we should check all the fields... */
1092         /*  checking SSID */
1093         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1094                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1095         if (p == NULL)
1096                 status = _STATS_FAILURE_;
1097
1098         if (ie_len == 0) { /*  broadcast ssid, however it is not allowed in assocreq */
1099                 status = _STATS_FAILURE_;
1100         } else {
1101                 /*  check if ssid match */
1102                 if (!_rtw_memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1103                         status = _STATS_FAILURE_;
1104
1105                 if (ie_len != cur->Ssid.SsidLength)
1106                         status = _STATS_FAILURE_;
1107         }
1108
1109         if (_STATS_SUCCESSFUL_ != status)
1110                 goto OnAssocReqFail;
1111
1112         /*  check if the supported rate is ok */
1113         p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1114         if (p == NULL) {
1115                 DBG_88E("Rx a sta assoc-req which supported rate is empty!\n");
1116                 /*  use our own rate set as statoin used */
1117                 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1118                 /* supportRateNum = AP_BSSRATE_LEN; */
1119
1120                 status = _STATS_FAILURE_;
1121                 goto OnAssocReqFail;
1122         } else {
1123                 memcpy(supportRate, p+2, ie_len);
1124                 supportRateNum = ie_len;
1125
1126                 p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
1127                                 pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1128                 if (p !=  NULL) {
1129                         if (supportRateNum <= sizeof(supportRate)) {
1130                                 memcpy(supportRate+supportRateNum, p+2, ie_len);
1131                                 supportRateNum += ie_len;
1132                         }
1133                 }
1134         }
1135
1136         /* todo: mask supportRate between AP & STA -> move to update raid */
1137         /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1138
1139         /* update station supportRate */
1140         pstat->bssratelen = supportRateNum;
1141         memcpy(pstat->bssrateset, supportRate, supportRateNum);
1142         UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1143
1144         /* check RSN/WPA/WPS */
1145         pstat->dot8021xalg = 0;
1146         pstat->wpa_psk = 0;
1147         pstat->wpa_group_cipher = 0;
1148         pstat->wpa2_group_cipher = 0;
1149         pstat->wpa_pairwise_cipher = 0;
1150         pstat->wpa2_pairwise_cipher = 0;
1151         _rtw_memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1152         if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1153                 int group_cipher = 0, pairwise_cipher = 0;
1154
1155                 wpa_ie = elems.rsn_ie;
1156                 wpa_ie_len = elems.rsn_ie_len;
1157
1158                 if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1159                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1160                         pstat->wpa_psk |= BIT(1);
1161
1162                         pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1163                         pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1164
1165                         if (!pstat->wpa2_group_cipher)
1166                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1167
1168                         if (!pstat->wpa2_pairwise_cipher)
1169                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1170                 } else {
1171                         status = WLAN_STATUS_INVALID_IE;
1172                 }
1173         } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1174                 int group_cipher = 0, pairwise_cipher = 0;
1175
1176                 wpa_ie = elems.wpa_ie;
1177                 wpa_ie_len = elems.wpa_ie_len;
1178
1179                 if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1180                         pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1181                         pstat->wpa_psk |= BIT(0);
1182
1183                         pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1184                         pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1185
1186                         if (!pstat->wpa_group_cipher)
1187                                 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1188
1189                         if (!pstat->wpa_pairwise_cipher)
1190                                 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1191                 } else {
1192                         status = WLAN_STATUS_INVALID_IE;
1193                 }
1194         } else {
1195                 wpa_ie = NULL;
1196                 wpa_ie_len = 0;
1197         }
1198
1199         if (_STATS_SUCCESSFUL_ != status)
1200                 goto OnAssocReqFail;
1201
1202         pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1203         if (wpa_ie == NULL) {
1204                 if (elems.wps_ie) {
1205                         DBG_88E("STA included WPS IE in "
1206                                    "(Re)Association Request - assume WPS is "
1207                                    "used\n");
1208                         pstat->flags |= WLAN_STA_WPS;
1209                         /* wpabuf_free(sta->wps_ie); */
1210                         /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1211                         /*                              elems.wps_ie_len - 4); */
1212                 } else {
1213                         DBG_88E("STA did not include WPA/RSN IE "
1214                                    "in (Re)Association Request - possible WPS "
1215                                    "use\n");
1216                         pstat->flags |= WLAN_STA_MAYBE_WPS;
1217                 }
1218
1219
1220                 /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1221                 /*  that the selected registrar of AP is _FLASE */
1222                 if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1223                         if (pmlmepriv->wps_beacon_ie) {
1224                                 u8 selected_registrar = 0;
1225
1226                                 rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
1227
1228                                 if (!selected_registrar) {
1229                                         DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n");
1230
1231                                         status = _STATS_UNABLE_HANDLE_STA_;
1232
1233                                         goto OnAssocReqFail;
1234                                 }
1235                         }
1236                 }
1237         } else {
1238                 int copy_len;
1239
1240                 if (psecuritypriv->wpa_psk == 0) {
1241                         DBG_88E("STA %pM: WPA/RSN IE in association "
1242                         "request, but AP don't support WPA/RSN\n", pstat->hwaddr);
1243
1244                         status = WLAN_STATUS_INVALID_IE;
1245
1246                         goto OnAssocReqFail;
1247                 }
1248
1249                 if (elems.wps_ie) {
1250                         DBG_88E("STA included WPS IE in "
1251                                    "(Re)Association Request - WPS is "
1252                                    "used\n");
1253                         pstat->flags |= WLAN_STA_WPS;
1254                         copy_len = 0;
1255                 } else {
1256                         copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len+2);
1257                 }
1258                 if (copy_len > 0)
1259                         memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1260         }
1261         /*  check if there is WMM IE & support WWM-PS */
1262         pstat->flags &= ~WLAN_STA_WME;
1263         pstat->qos_option = 0;
1264         pstat->qos_info = 0;
1265         pstat->has_legacy_ac = true;
1266         pstat->uapsd_vo = 0;
1267         pstat->uapsd_vi = 0;
1268         pstat->uapsd_be = 0;
1269         pstat->uapsd_bk = 0;
1270         if (pmlmepriv->qospriv.qos_option) {
1271                 p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1272                 for (;;) {
1273                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1274                         if (p != NULL) {
1275                                 if (_rtw_memcmp(p+2, WMM_IE, 6)) {
1276                                         pstat->flags |= WLAN_STA_WME;
1277
1278                                         pstat->qos_option = 1;
1279                                         pstat->qos_info = *(p+8);
1280
1281                                         pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1282
1283                                         if ((pstat->qos_info&0xf) != 0xf)
1284                                                 pstat->has_legacy_ac = true;
1285                                         else
1286                                                 pstat->has_legacy_ac = false;
1287
1288                                         if (pstat->qos_info&0xf) {
1289                                                 if (pstat->qos_info&BIT(0))
1290                                                         pstat->uapsd_vo = BIT(0)|BIT(1);
1291                                                 else
1292                                                         pstat->uapsd_vo = 0;
1293
1294                                                 if (pstat->qos_info&BIT(1))
1295                                                         pstat->uapsd_vi = BIT(0)|BIT(1);
1296                                                 else
1297                                                         pstat->uapsd_vi = 0;
1298
1299                                                 if (pstat->qos_info&BIT(2))
1300                                                         pstat->uapsd_bk = BIT(0)|BIT(1);
1301                                                 else
1302                                                         pstat->uapsd_bk = 0;
1303
1304                                                 if (pstat->qos_info&BIT(3))
1305                                                         pstat->uapsd_be = BIT(0)|BIT(1);
1306                                                 else
1307                                                         pstat->uapsd_be = 0;
1308                                         }
1309                                         break;
1310                                 }
1311                         } else {
1312                                 break;
1313                         }
1314                         p = p + ie_len + 2;
1315                 }
1316         }
1317
1318         /* save HT capabilities in the sta object */
1319         _rtw_memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
1320         if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
1321                 pstat->flags |= WLAN_STA_HT;
1322
1323                 pstat->flags |= WLAN_STA_WME;
1324
1325                 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
1326         } else {
1327                 pstat->flags &= ~WLAN_STA_HT;
1328         }
1329         if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags&WLAN_STA_HT)) {
1330                 status = _STATS_FAILURE_;
1331                 goto OnAssocReqFail;
1332         }
1333
1334         if ((pstat->flags & WLAN_STA_HT) &&
1335             ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1336             (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1337                 DBG_88E("HT: %pM tried to "
1338                         "use TKIP with HT association\n", pstat->hwaddr);
1339
1340                 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1341                 /* goto OnAssocReqFail; */
1342         }
1343
1344         pstat->flags |= WLAN_STA_NONERP;
1345         for (i = 0; i < pstat->bssratelen; i++) {
1346                 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1347                         pstat->flags &= ~WLAN_STA_NONERP;
1348                         break;
1349                 }
1350         }
1351
1352         if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1353                 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1354         else
1355                 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1356
1357
1358
1359         if (status != _STATS_SUCCESSFUL_)
1360                 goto OnAssocReqFail;
1361
1362 #ifdef CONFIG_88EU_P2P
1363         pstat->is_p2p_device = false;
1364         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1365                 p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen);
1366                 if (p2pie) {
1367                         pstat->is_p2p_device = true;
1368                         p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
1369                         if (p2p_status_code > 0) {
1370                                 pstat->p2p_status_code = p2p_status_code;
1371                                 status = _STATS_CAP_FAIL_;
1372                                 goto OnAssocReqFail;
1373                         }
1374                 }
1375         }
1376         pstat->p2p_status_code = p2p_status_code;
1377 #endif /* CONFIG_88EU_P2P */
1378
1379         /* TODO: identify_proprietary_vendor_ie(); */
1380         /*  Realtek proprietary IE */
1381         /*  identify if this is Broadcom sta */
1382         /*  identify if this is ralink sta */
1383         /*  Customer proprietary IE */
1384
1385         /* get a unique AID */
1386         if (pstat->aid > 0) {
1387                 DBG_88E("  old AID %d\n", pstat->aid);
1388         } else {
1389                 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1390                         if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1391                                 break;
1392
1393                 /* if (pstat->aid > NUM_STA) { */
1394                 if (pstat->aid > pstapriv->max_num_sta) {
1395                         pstat->aid = 0;
1396
1397                         DBG_88E("  no room for more AIDs\n");
1398
1399                         status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1400
1401                         goto OnAssocReqFail;
1402                 } else {
1403                         pstapriv->sta_aid[pstat->aid - 1] = pstat;
1404                         DBG_88E("allocate new AID=(%d)\n", pstat->aid);
1405                 }
1406         }
1407
1408         pstat->state &= (~WIFI_FW_ASSOC_STATE);
1409         pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1410
1411         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
1412         if (!rtw_is_list_empty(&pstat->auth_list)) {
1413                 rtw_list_delete(&pstat->auth_list);
1414                 pstapriv->auth_list_cnt--;
1415         }
1416         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
1417
1418         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1419         if (rtw_is_list_empty(&pstat->asoc_list)) {
1420                 pstat->expire_to = pstapriv->expire_to;
1421                 rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1422                 pstapriv->asoc_list_cnt++;
1423         }
1424         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1425
1426         /*  now the station is qualified to join our BSS... */
1427         if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
1428 #ifdef CONFIG_88EU_AP_MODE
1429                 /* 1 bss_cap_update & sta_info_update */
1430                 bss_cap_update_on_sta_join(padapter, pstat);
1431                 sta_info_update(padapter, pstat);
1432
1433                 /* issue assoc rsp before notify station join event. */
1434                 if (frame_type == WIFI_ASSOCREQ)
1435                         issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1436                 else
1437                         issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1438
1439                 /* 2 - report to upper layer */
1440                 DBG_88E("indicate_sta_join_event to upper layer - hostapd\n");
1441                 rtw_indicate_sta_assoc_event(padapter, pstat);
1442
1443                 /* 3-(1) report sta add event */
1444                 report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1445 #endif
1446         }
1447
1448         return _SUCCESS;
1449
1450 asoc_class2_error:
1451
1452 #ifdef CONFIG_88EU_AP_MODE
1453         issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1454 #endif
1455
1456         return _FAIL;
1457
1458 OnAssocReqFail:
1459
1460
1461 #ifdef CONFIG_88EU_AP_MODE
1462         pstat->aid = 0;
1463         if (frame_type == WIFI_ASSOCREQ)
1464                 issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1465         else
1466                 issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1467 #endif
1468
1469
1470 #endif /* CONFIG_88EU_AP_MODE */
1471
1472         return _FAIL;
1473 }
1474
1475 unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1476 {
1477         uint i;
1478         int res;
1479         unsigned short  status;
1480         struct ndis_802_11_var_ie *pIE;
1481         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1482         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1483         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1484         /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
1485         u8 *pframe = precv_frame->u.hdr.rx_data;
1486         uint pkt_len = precv_frame->u.hdr.len;
1487
1488         DBG_88E("%s\n", __func__);
1489
1490         /* check A1 matches or not */
1491         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1492                 return _SUCCESS;
1493
1494         if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1495                 return _SUCCESS;
1496
1497         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1498                 return _SUCCESS;
1499
1500         _cancel_timer_ex(&pmlmeext->link_timer);
1501
1502         /* status */
1503         status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1504         if (status > 0) {
1505                 DBG_88E("assoc reject, status code: %d\n", status);
1506                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1507                 res = -4;
1508                 goto report_assoc_result;
1509         }
1510
1511         /* get capabilities */
1512         pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1513
1514         /* set slot time */
1515         pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1516
1517         /* AID */
1518         pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1519         res = pmlmeinfo->aid;
1520
1521         /* following are moved to join event callback function */
1522         /* to handle HT, WMM, rate adaptive, update MAC reg */
1523         /* for not to handle the synchronous IO in the tasklet */
1524         for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1525                 pIE = (struct ndis_802_11_var_ie *)(pframe + i);
1526
1527                 switch (pIE->ElementID) {
1528                 case _VENDOR_SPECIFIC_IE_:
1529                         if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6))    /* WMM */
1530                                 WMM_param_handler(padapter, pIE);
1531                         break;
1532                 case _HT_CAPABILITY_IE_:        /* HT caps */
1533                         HT_caps_handler(padapter, pIE);
1534                         break;
1535                 case _HT_EXTRA_INFO_IE_:        /* HT info */
1536                         HT_info_handler(padapter, pIE);
1537                         break;
1538                 case _ERPINFO_IE_:
1539                         ERP_IE_handler(padapter, pIE);
1540                 default:
1541                         break;
1542                 }
1543
1544                 i += (pIE->Length + 2);
1545         }
1546
1547         pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1548         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1549
1550         /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1551         UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
1552
1553 report_assoc_result:
1554         if (res > 0) {
1555                 rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1556         } else {
1557                 rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1558         }
1559
1560         report_join_res(padapter, res);
1561
1562         return _SUCCESS;
1563 }
1564
1565 unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1566 {
1567         unsigned short  reason;
1568         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1569         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1570         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1571         u8 *pframe = precv_frame->u.hdr.rx_data;
1572 #ifdef CONFIG_88EU_P2P
1573         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1574 #endif /* CONFIG_88EU_P2P */
1575
1576         /* check A3 */
1577         if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1578                 return _SUCCESS;
1579
1580 #ifdef CONFIG_88EU_P2P
1581         if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1582                 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1583                 _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1584         }
1585 #endif /* CONFIG_88EU_P2P */
1586
1587         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1588
1589         DBG_88E("%s Reason code(%d)\n", __func__, reason);
1590
1591 #ifdef CONFIG_88EU_AP_MODE
1592         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1593                 unsigned long irqL;
1594                 struct sta_info *psta;
1595                 struct sta_priv *pstapriv = &padapter->stapriv;
1596
1597                 DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
1598                               reason, GetAddr2Ptr(pframe));
1599
1600                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1601                 if (psta) {
1602                         u8 updated = 0;
1603
1604                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1605                         if (!rtw_is_list_empty(&psta->asoc_list)) {
1606                                 rtw_list_delete(&psta->asoc_list);
1607                                 pstapriv->asoc_list_cnt--;
1608                                 updated = ap_free_sta(padapter, psta, false, reason);
1609                         }
1610                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1611
1612                         associated_clients_update(padapter, updated);
1613                 }
1614
1615
1616                 return _SUCCESS;
1617         } else
1618 #endif
1619         {
1620                 DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n",
1621                               reason, GetAddr3Ptr(pframe));
1622
1623                 receive_disconnect(padapter, GetAddr3Ptr(pframe) , reason);
1624         }
1625         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1626         return _SUCCESS;
1627 }
1628
1629 unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1630 {
1631         u16 reason;
1632         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1633         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1634         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1635         u8 *pframe = precv_frame->u.hdr.rx_data;
1636 #ifdef CONFIG_88EU_P2P
1637         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1638 #endif /* CONFIG_88EU_P2P */
1639
1640         /* check A3 */
1641         if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1642                 return _SUCCESS;
1643
1644 #ifdef CONFIG_88EU_P2P
1645         if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1646                 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1647                 _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1648         }
1649 #endif /* CONFIG_88EU_P2P */
1650
1651         reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1652
1653         DBG_88E("%s Reason code(%d)\n", __func__, reason);
1654
1655 #ifdef CONFIG_88EU_AP_MODE
1656         if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1657                 unsigned long irqL;
1658                 struct sta_info *psta;
1659                 struct sta_priv *pstapriv = &padapter->stapriv;
1660
1661                 /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
1662                 /* rtw_free_stainfo(padapter, psta); */
1663                 /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
1664
1665                 DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
1666                               reason, GetAddr2Ptr(pframe));
1667
1668                 psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1669                 if (psta) {
1670                         u8 updated = 0;
1671
1672                         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1673                         if (!rtw_is_list_empty(&psta->asoc_list)) {
1674                                 rtw_list_delete(&psta->asoc_list);
1675                                 pstapriv->asoc_list_cnt--;
1676                                 updated = ap_free_sta(padapter, psta, false, reason);
1677                         }
1678                         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1679
1680                         associated_clients_update(padapter, updated);
1681                 }
1682
1683                 return _SUCCESS;
1684         } else
1685 #endif
1686         {
1687                 DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
1688                               reason, GetAddr3Ptr(pframe));
1689
1690                 receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1691         }
1692         pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1693         return _SUCCESS;
1694 }
1695
1696 unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1697 {
1698         DBG_88E("%s\n", __func__);
1699         return _SUCCESS;
1700 }
1701
1702 unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1703 {
1704         unsigned int ret = _FAIL;
1705         struct sta_info *psta = NULL;
1706         struct sta_priv *pstapriv = &padapter->stapriv;
1707         u8 *pframe = precv_frame->u.hdr.rx_data;
1708         u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1709         u8 category;
1710         u8 action;
1711
1712         DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1713
1714         psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1715
1716         if (!psta)
1717                 goto exit;
1718
1719         category = frame_body[0];
1720         if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1721                 goto exit;
1722
1723         action = frame_body[1];
1724         switch (action) {
1725         case RTW_WLAN_ACTION_SPCT_MSR_REQ:
1726         case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
1727         case RTW_WLAN_ACTION_SPCT_TPC_REQ:
1728         case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
1729                 break;
1730         case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
1731                 break;
1732         default:
1733                 break;
1734         }
1735
1736 exit:
1737         return ret;
1738 }
1739
1740 unsigned int OnAction_qos(struct adapter *padapter, union recv_frame *precv_frame)
1741 {
1742         return _SUCCESS;
1743 }
1744
1745 unsigned int OnAction_dls(struct adapter *padapter, union recv_frame *precv_frame)
1746 {
1747         return _SUCCESS;
1748 }
1749
1750 unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1751 {
1752         u8 *addr;
1753         struct sta_info *psta = NULL;
1754         struct recv_reorder_ctrl *preorder_ctrl;
1755         unsigned char           *frame_body;
1756         unsigned char           category, action;
1757         unsigned short  tid, status, reason_code = 0;
1758         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1759         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1760         u8 *pframe = precv_frame->u.hdr.rx_data;
1761         struct sta_priv *pstapriv = &padapter->stapriv;
1762         /* check RA matches or not */
1763         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1764                 return _SUCCESS;
1765
1766         DBG_88E("%s\n", __func__);
1767
1768         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1769                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1770                         return _SUCCESS;
1771
1772         addr = GetAddr2Ptr(pframe);
1773         psta = rtw_get_stainfo(pstapriv, addr);
1774
1775         if (psta == NULL)
1776                 return _SUCCESS;
1777
1778         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1779
1780         category = frame_body[0];
1781         if (category == RTW_WLAN_CATEGORY_BACK) { /*  representing Block Ack */
1782                 if (!pmlmeinfo->HT_enable)
1783                         return _SUCCESS;
1784                 action = frame_body[1];
1785                 DBG_88E("%s, action=%d\n", __func__, action);
1786                 switch (action) {
1787                 case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1788                         memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1789                         process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1790
1791                         if (pmlmeinfo->bAcceptAddbaReq)
1792                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
1793                         else
1794                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1795                         break;
1796                 case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1797                         status = RTW_GET_LE16(&frame_body[3]);
1798                         tid = ((frame_body[5] >> 2) & 0x7);
1799                         if (status == 0) {      /* successful */
1800                                 DBG_88E("agg_enable for TID=%d\n", tid);
1801                                 psta->htpriv.agg_enable_bitmap |= 1 << tid;
1802                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1803                         } else {
1804                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1805                         }
1806                         break;
1807                 case RTW_WLAN_ACTION_DELBA: /* DELBA */
1808                         if ((frame_body[3] & BIT(3)) == 0) {
1809                                 psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
1810                                 psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
1811                                 reason_code = RTW_GET_LE16(&frame_body[4]);
1812                         } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
1813                                 tid = (frame_body[3] >> 4) & 0x0F;
1814                                 preorder_ctrl =  &psta->recvreorder_ctrl[tid];
1815                                 preorder_ctrl->enable = false;
1816                                 preorder_ctrl->indicate_seq = 0xffff;
1817                         }
1818                         DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
1819                         /* todo: how to notify the host while receiving DELETE BA */
1820                         break;
1821                 default:
1822                         break;
1823                 }
1824         }
1825         return _SUCCESS;
1826 }
1827
1828 #ifdef CONFIG_88EU_P2P
1829
1830 static int get_reg_classes_full_count(struct p2p_channels *channel_list)
1831 {
1832         int cnt = 0;
1833         int i;
1834
1835         for (i = 0; i < channel_list->reg_classes; i++) {
1836                 cnt += channel_list->reg_class[i].channels;
1837         }
1838
1839         return cnt;
1840 }
1841
1842 void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
1843 {
1844         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
1845         u8 action = P2P_PUB_ACTION_ACTION;
1846         __be32 p2poui = cpu_to_be32(P2POUI);
1847         u8 oui_subtype = P2P_GO_NEGO_REQ;
1848         u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
1849         u8 wpsielen = 0, p2pielen = 0;
1850         u16 len_channellist_attr = 0;
1851         struct xmit_frame *pmgntframe;
1852         struct pkt_attrib *pattrib;
1853         unsigned char *pframe;
1854         struct rtw_ieee80211_hdr        *pwlanhdr;
1855         __le16 *fctrl;
1856         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1857         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1858         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
1859
1860         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1861         if (pmgntframe == NULL)
1862                 return;
1863
1864         DBG_88E("[%s] In\n", __func__);
1865         /* update attribute */
1866         pattrib = &pmgntframe->attrib;
1867         update_mgntframe_attrib(padapter, pattrib);
1868
1869         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1870
1871         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1872         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1873
1874         fctrl = &(pwlanhdr->frame_ctl);
1875         *(fctrl) = 0;
1876
1877         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
1878         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1879         memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
1880
1881         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1882         pmlmeext->mgnt_seq++;
1883         SetFrameSubType(pframe, WIFI_ACTION);
1884
1885         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1886         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1887
1888         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1889         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1890         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
1891         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
1892         pwdinfo->negotiation_dialog_token = 1;  /*      Initialize the dialog value */
1893         pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
1894
1895
1896
1897         /*      WPS Section */
1898         wpsielen = 0;
1899         /*      WPS OUI */
1900         *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
1901         wpsielen += 4;
1902
1903         /*      WPS version */
1904         /*      Type: */
1905         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
1906         wpsielen += 2;
1907
1908         /*      Length: */
1909         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
1910         wpsielen += 2;
1911
1912         /*      Value: */
1913         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
1914
1915         /*      Device Password ID */
1916         /*      Type: */
1917         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
1918         wpsielen += 2;
1919
1920         /*      Length: */
1921         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
1922         wpsielen += 2;
1923
1924         /*      Value: */
1925
1926         if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
1927                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
1928         else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
1929                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
1930         else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
1931                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
1932
1933         wpsielen += 2;
1934
1935         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
1936
1937
1938         /*      P2P IE Section. */
1939
1940         /*      P2P OUI */
1941         p2pielen = 0;
1942         p2pie[p2pielen++] = 0x50;
1943         p2pie[p2pielen++] = 0x6F;
1944         p2pie[p2pielen++] = 0x9A;
1945         p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
1946
1947         /*      Commented by Albert 20110306 */
1948         /*      According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
1949         /*      1. P2P Capability */
1950         /*      2. Group Owner Intent */
1951         /*      3. Configuration Timeout */
1952         /*      4. Listen Channel */
1953         /*      5. Extended Listen Timing */
1954         /*      6. Intended P2P Interface Address */
1955         /*      7. Channel List */
1956         /*      8. P2P Device Info */
1957         /*      9. Operating Channel */
1958
1959
1960         /*      P2P Capability */
1961         /*      Type: */
1962         p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
1963
1964         /*      Length: */
1965         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1966         p2pielen += 2;
1967
1968         /*      Value: */
1969         /*      Device Capability Bitmap, 1 byte */
1970         p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
1971
1972         /*      Group Capability Bitmap, 1 byte */
1973         if (pwdinfo->persistent_supported)
1974                 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
1975         else
1976                 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
1977
1978         /*      Group Owner Intent */
1979         /*      Type: */
1980         p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
1981
1982         /*      Length: */
1983         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
1984         p2pielen += 2;
1985
1986         /*      Value: */
1987         /*      Todo the tie breaker bit. */
1988         p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
1989
1990         /*      Configuration Timeout */
1991         /*      Type: */
1992         p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
1993
1994         /*      Length: */
1995         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1996         p2pielen += 2;
1997
1998         /*      Value: */
1999         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
2000         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
2001
2002
2003         /*      Listen Channel */
2004         /*      Type: */
2005         p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
2006
2007         /*      Length: */
2008         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2009         p2pielen += 2;
2010
2011         /*      Value: */
2012         /*      Country String */
2013         p2pie[p2pielen++] = 'X';
2014         p2pie[p2pielen++] = 'X';
2015
2016         /*      The third byte should be set to 0x04. */
2017         /*      Described in the "Operating Channel Attribute" section. */
2018         p2pie[p2pielen++] = 0x04;
2019
2020         /*      Operating Class */
2021         p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
2022
2023         /*      Channel Number */
2024         p2pie[p2pielen++] = pwdinfo->listen_channel;    /*      listening channel number */
2025
2026
2027         /*      Extended Listen Timing ATTR */
2028         /*      Type: */
2029         p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
2030
2031         /*      Length: */
2032         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
2033         p2pielen += 2;
2034
2035         /*      Value: */
2036         /*      Availability Period */
2037         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2038         p2pielen += 2;
2039
2040         /*      Availability Interval */
2041         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2042         p2pielen += 2;
2043
2044
2045         /*      Intended P2P Interface Address */
2046         /*      Type: */
2047         p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2048
2049         /*      Length: */
2050         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2051         p2pielen += 2;
2052
2053         /*      Value: */
2054         memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2055         p2pielen += ETH_ALEN;
2056
2057
2058         /*      Channel List */
2059         /*      Type: */
2060         p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2061
2062         /*  Length: */
2063         /*  Country String(3) */
2064         /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2065         /*  + number of channels in all classes */
2066         len_channellist_attr = 3
2067            + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
2068            + get_reg_classes_full_count(&pmlmeext->channel_list);
2069
2070         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2071         p2pielen += 2;
2072
2073         /*      Value: */
2074         /*      Country String */
2075         p2pie[p2pielen++] = 'X';
2076         p2pie[p2pielen++] = 'X';
2077
2078         /*      The third byte should be set to 0x04. */
2079         /*      Described in the "Operating Channel Attribute" section. */
2080         p2pie[p2pielen++] = 0x04;
2081
2082         /*      Channel Entry List */
2083
2084         {
2085                 int i, j;
2086                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2087                         /*      Operating Class */
2088                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2089
2090                         /*      Number of Channels */
2091                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2092
2093                         /*      Channel List */
2094                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2095                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2096                         }
2097                 }
2098         }
2099
2100         /*      Device Info */
2101         /*      Type: */
2102         p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2103
2104         /*      Length: */
2105         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2106         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2107         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2108         p2pielen += 2;
2109
2110         /*      Value: */
2111         /*      P2P Device Address */
2112         memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2113         p2pielen += ETH_ALEN;
2114
2115         /*      Config Method */
2116         /*      This field should be big endian. Noted by P2P specification. */
2117
2118         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2119
2120         p2pielen += 2;
2121
2122         /*      Primary Device Type */
2123         /*      Category ID */
2124         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2125         p2pielen += 2;
2126
2127         /*      OUI */
2128         *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2129         p2pielen += 4;
2130
2131         /*      Sub Category ID */
2132         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2133         p2pielen += 2;
2134
2135         /*      Number of Secondary Device Types */
2136         p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
2137
2138         /*      Device Name */
2139         /*      Type: */
2140         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2141         p2pielen += 2;
2142
2143         /*      Length: */
2144         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2145         p2pielen += 2;
2146
2147         /*      Value: */
2148         memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
2149         p2pielen += pwdinfo->device_name_len;
2150
2151
2152         /*      Operating Channel */
2153         /*      Type: */
2154         p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2155
2156         /*      Length: */
2157         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2158         p2pielen += 2;
2159
2160         /*      Value: */
2161         /*      Country String */
2162         p2pie[p2pielen++] = 'X';
2163         p2pie[p2pielen++] = 'X';
2164
2165         /*      The third byte should be set to 0x04. */
2166         /*      Described in the "Operating Channel Attribute" section. */
2167         p2pie[p2pielen++] = 0x04;
2168
2169         /*      Operating Class */
2170         p2pie[p2pielen++] = 0x51;
2171
2172         /*      Channel Number */
2173         p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
2174
2175         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2176
2177         pattrib->last_txcmdsz = pattrib->pktlen;
2178
2179         dump_mgntframe(padapter, pmgntframe);
2180
2181         return;
2182 }
2183
2184 static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
2185 {
2186         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2187         u8 action = P2P_PUB_ACTION_ACTION;
2188         __be32                  p2poui = cpu_to_be32(P2POUI);
2189         u8 oui_subtype = P2P_GO_NEGO_RESP;
2190         u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
2191         u8 p2pielen = 0;
2192         uint                    wpsielen = 0;
2193         u16 wps_devicepassword_id = 0x0000;
2194         __be16                  be_tmp;
2195         uint                    wps_devicepassword_id_len = 0;
2196         u16 len_channellist_attr = 0;
2197
2198         struct xmit_frame                       *pmgntframe;
2199         struct pkt_attrib                       *pattrib;
2200         unsigned char                                   *pframe;
2201         struct rtw_ieee80211_hdr        *pwlanhdr;
2202         __le16 *fctrl;
2203         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2204         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2205         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2206
2207         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2208         if (pmgntframe == NULL)
2209                 return;
2210
2211         DBG_88E("[%s] In, result=%d\n", __func__,  result);
2212         /* update attribute */
2213         pattrib = &pmgntframe->attrib;
2214         update_mgntframe_attrib(padapter, pattrib);
2215
2216         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2217
2218         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2219         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2220
2221         fctrl = &(pwlanhdr->frame_ctl);
2222         *(fctrl) = 0;
2223
2224         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2225         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2226         memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2227
2228         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2229         pmlmeext->mgnt_seq++;
2230         SetFrameSubType(pframe, WIFI_ACTION);
2231
2232         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2233         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2234
2235         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2236         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2237         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
2238         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2239         pwdinfo->negotiation_dialog_token = frame_body[7];      /*      The Dialog Token of provisioning discovery request frame. */
2240         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
2241
2242         /*      Commented by Albert 20110328 */
2243         /*      Try to get the device password ID from the WPS IE of group negotiation request frame */
2244         /*      WiFi Direct test plan 5.1.15 */
2245         rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
2246         rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
2247         wps_devicepassword_id = be16_to_cpu(be_tmp);
2248
2249         _rtw_memset(wpsie, 0x00, 255);
2250         wpsielen = 0;
2251
2252         /*      WPS Section */
2253         wpsielen = 0;
2254         /*      WPS OUI */
2255         *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
2256         wpsielen += 4;
2257
2258         /*      WPS version */
2259         /*      Type: */
2260         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2261         wpsielen += 2;
2262
2263         /*      Length: */
2264         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
2265         wpsielen += 2;
2266
2267         /*      Value: */
2268         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
2269
2270         /*      Device Password ID */
2271         /*      Type: */
2272         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2273         wpsielen += 2;
2274
2275         /*      Length: */
2276         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
2277         wpsielen += 2;
2278
2279         /*      Value: */
2280         if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2281                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2282         else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2283                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2284         else
2285                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2286         wpsielen += 2;
2287
2288         /*      Commented by Kurt 20120113 */
2289         /*      If some device wants to do p2p handshake without sending prov_disc_req */
2290         /*      We have to get peer_req_cm from here. */
2291         if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2292                 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2293                         memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2294                 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2295                         memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2296                 else
2297                         memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2298         }
2299
2300         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
2301
2302
2303         /*      P2P IE Section. */
2304
2305         /*      P2P OUI */
2306         p2pielen = 0;
2307         p2pie[p2pielen++] = 0x50;
2308         p2pie[p2pielen++] = 0x6F;
2309         p2pie[p2pielen++] = 0x9A;
2310         p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
2311
2312         /*      Commented by Albert 20100908 */
2313         /*      According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
2314         /*      1. Status */
2315         /*      2. P2P Capability */
2316         /*      3. Group Owner Intent */
2317         /*      4. Configuration Timeout */
2318         /*      5. Operating Channel */
2319         /*      6. Intended P2P Interface Address */
2320         /*      7. Channel List */
2321         /*      8. Device Info */
2322         /*      9. Group ID     (Only GO) */
2323
2324
2325         /*      ToDo: */
2326
2327         /*      P2P Status */
2328         /*      Type: */
2329         p2pie[p2pielen++] = P2P_ATTR_STATUS;
2330
2331         /*      Length: */
2332         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2333         p2pielen += 2;
2334
2335         /*      Value: */
2336         p2pie[p2pielen++] = result;
2337
2338         /*      P2P Capability */
2339         /*      Type: */
2340         p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2341
2342         /*      Length: */
2343         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2344         p2pielen += 2;
2345
2346         /*      Value: */
2347         /*      Device Capability Bitmap, 1 byte */
2348
2349         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2350                 /*      Commented by Albert 2011/03/08 */
2351                 /*      According to the P2P specification */
2352                 /*      if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
2353                 p2pie[p2pielen++] = 0;
2354         } else {
2355                 /*      Be group owner or meet the error case */
2356                 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2357         }
2358
2359         /*      Group Capability Bitmap, 1 byte */
2360         if (pwdinfo->persistent_supported) {
2361                 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2362         } else {
2363                 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2364         }
2365
2366         /*      Group Owner Intent */
2367         /*      Type: */
2368         p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2369
2370         /*      Length: */
2371         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2372         p2pielen += 2;
2373
2374         /*      Value: */
2375         if (pwdinfo->peer_intent & 0x01) {
2376                 /*      Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
2377                 p2pie[p2pielen++] = (pwdinfo->intent << 1);
2378         } else {
2379                 /*      Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
2380                 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2381         }
2382
2383
2384         /*      Configuration Timeout */
2385         /*      Type: */
2386         p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2387
2388         /*      Length: */
2389         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2390         p2pielen += 2;
2391
2392         /*      Value: */
2393         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
2394         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
2395
2396         /*      Operating Channel */
2397         /*      Type: */
2398         p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2399
2400         /*      Length: */
2401         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2402         p2pielen += 2;
2403
2404         /*      Value: */
2405         /*      Country String */
2406         p2pie[p2pielen++] = 'X';
2407         p2pie[p2pielen++] = 'X';
2408
2409         /*      The third byte should be set to 0x04. */
2410         /*      Described in the "Operating Channel Attribute" section. */
2411         p2pie[p2pielen++] = 0x04;
2412
2413         /*      Operating Class */
2414         p2pie[p2pielen++] = 0x51;
2415
2416         /*      Channel Number */
2417         p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
2418
2419         /*      Intended P2P Interface Address */
2420         /*      Type: */
2421         p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2422
2423         /*      Length: */
2424         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2425         p2pielen += 2;
2426
2427         /*      Value: */
2428         memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2429         p2pielen += ETH_ALEN;
2430
2431         /*      Channel List */
2432         /*      Type: */
2433         p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2434
2435         /*  Country String(3) */
2436         /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2437         /*  + number of channels in all classes */
2438         len_channellist_attr = 3
2439            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2440            + get_reg_classes_full_count(&pmlmeext->channel_list);
2441
2442         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2443
2444         p2pielen += 2;
2445
2446         /*      Value: */
2447         /*      Country String */
2448         p2pie[p2pielen++] = 'X';
2449         p2pie[p2pielen++] = 'X';
2450
2451         /*      The third byte should be set to 0x04. */
2452         /*      Described in the "Operating Channel Attribute" section. */
2453         p2pie[p2pielen++] = 0x04;
2454
2455         /*      Channel Entry List */
2456
2457         {
2458                 int i, j;
2459                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2460                         /*      Operating Class */
2461                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2462
2463                         /*      Number of Channels */
2464                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2465
2466                         /*      Channel List */
2467                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2468                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2469                         }
2470                 }
2471         }
2472
2473         /*      Device Info */
2474         /*      Type: */
2475         p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2476
2477         /*      Length: */
2478         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2479         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2480         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2481         p2pielen += 2;
2482
2483         /*      Value: */
2484         /*      P2P Device Address */
2485         memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2486         p2pielen += ETH_ALEN;
2487
2488         /*      Config Method */
2489         /*      This field should be big endian. Noted by P2P specification. */
2490
2491         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2492
2493         p2pielen += 2;
2494
2495         /*      Primary Device Type */
2496         /*      Category ID */
2497         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2498         p2pielen += 2;
2499
2500         /*      OUI */
2501         *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2502         p2pielen += 4;
2503
2504         /*      Sub Category ID */
2505         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2506         p2pielen += 2;
2507
2508         /*      Number of Secondary Device Types */
2509         p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
2510
2511         /*      Device Name */
2512         /*      Type: */
2513         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2514         p2pielen += 2;
2515
2516         /*      Length: */
2517         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2518         p2pielen += 2;
2519
2520         /*      Value: */
2521         memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
2522         p2pielen += pwdinfo->device_name_len;
2523
2524         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2525                 /*      Group ID Attribute */
2526                 /*      Type: */
2527                 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2528
2529                 /*      Length: */
2530                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2531                 p2pielen += 2;
2532
2533                 /*      Value: */
2534                 /*      p2P Device Address */
2535                 memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
2536                 p2pielen += ETH_ALEN;
2537
2538                 /*      SSID */
2539                 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2540                 p2pielen += pwdinfo->nego_ssidlen;
2541         }
2542
2543         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2544
2545         pattrib->last_txcmdsz = pattrib->pktlen;
2546
2547         dump_mgntframe(padapter, pmgntframe);
2548         return;
2549 }
2550
2551 static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
2552 {
2553         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2554         u8 action = P2P_PUB_ACTION_ACTION;
2555         __be32                  p2poui = cpu_to_be32(P2POUI);
2556         u8 oui_subtype = P2P_GO_NEGO_CONF;
2557         u8 p2pie[255] = { 0x00 };
2558         u8 p2pielen = 0;
2559
2560         struct xmit_frame                       *pmgntframe;
2561         struct pkt_attrib                       *pattrib;
2562         unsigned char                                   *pframe;
2563         struct rtw_ieee80211_hdr        *pwlanhdr;
2564         __le16 *fctrl;
2565         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2566         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2567         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2568
2569         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2570         if (pmgntframe == NULL)
2571                 return;
2572
2573         DBG_88E("[%s] In\n", __func__);
2574         /* update attribute */
2575         pattrib = &pmgntframe->attrib;
2576         update_mgntframe_attrib(padapter, pattrib);
2577
2578         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2579
2580         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2581         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2582
2583         fctrl = &(pwlanhdr->frame_ctl);
2584         *(fctrl) = 0;
2585
2586         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2587         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2588         memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2589
2590         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2591         pmlmeext->mgnt_seq++;
2592         SetFrameSubType(pframe, WIFI_ACTION);
2593
2594         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2595         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2596
2597         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2598         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2599         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
2600         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2601         pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
2602
2603
2604
2605         /*      P2P IE Section. */
2606
2607         /*      P2P OUI */
2608         p2pielen = 0;
2609         p2pie[p2pielen++] = 0x50;
2610         p2pie[p2pielen++] = 0x6F;
2611         p2pie[p2pielen++] = 0x9A;
2612         p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
2613
2614         /*      Commented by Albert 20110306 */
2615         /*      According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
2616         /*      1. Status */
2617         /*      2. P2P Capability */
2618         /*      3. Operating Channel */
2619         /*      4. Channel List */
2620         /*      5. Group ID     (if this WiFi is GO) */
2621
2622         /*      P2P Status */
2623         /*      Type: */
2624         p2pie[p2pielen++] = P2P_ATTR_STATUS;
2625
2626         /*      Length: */
2627         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2628         p2pielen += 2;
2629
2630         /*      Value: */
2631         p2pie[p2pielen++] = result;
2632
2633         /*      P2P Capability */
2634         /*      Type: */
2635         p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2636
2637         /*      Length: */
2638         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2639         p2pielen += 2;
2640
2641         /*      Value: */
2642         /*      Device Capability Bitmap, 1 byte */
2643         p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2644
2645         /*      Group Capability Bitmap, 1 byte */
2646         if (pwdinfo->persistent_supported)
2647                 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2648         else
2649                 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2650
2651         /*      Operating Channel */
2652         /*      Type: */
2653         p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2654
2655         /*      Length: */
2656         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2657         p2pielen += 2;
2658
2659         /*      Value: */
2660         /*      Country String */
2661         p2pie[p2pielen++] = 'X';
2662         p2pie[p2pielen++] = 'X';
2663
2664         /*      The third byte should be set to 0x04. */
2665         /*      Described in the "Operating Channel Attribute" section. */
2666         p2pie[p2pielen++] = 0x04;
2667
2668
2669         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2670                 /*      Operating Class */
2671                 p2pie[p2pielen++] = 0x51;
2672                 p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
2673         } else {
2674                 /*      Operating Class */
2675                 p2pie[p2pielen++] = 0x51;
2676
2677                 /*      Channel Number */
2678                 p2pie[p2pielen++] = pwdinfo->operating_channel;         /*      Use the listen channel as the operating channel */
2679         }
2680
2681
2682         /*      Channel List */
2683         /*      Type: */
2684         p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2685
2686         /*      Length: */
2687         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len);
2688         p2pielen += 2;
2689
2690         /*      Value: */
2691         memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len);
2692         p2pielen += pwdinfo->channel_list_attr_len;
2693
2694         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2695                 /*      Group ID Attribute */
2696                 /*      Type: */
2697                 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2698
2699                 /*      Length: */
2700                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2701                 p2pielen += 2;
2702
2703                 /*      Value: */
2704                 /*      p2P Device Address */
2705                 memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
2706                 p2pielen += ETH_ALEN;
2707
2708                 /*      SSID */
2709                 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2710                 p2pielen += pwdinfo->nego_ssidlen;
2711         }
2712         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2713         pattrib->last_txcmdsz = pattrib->pktlen;
2714         dump_mgntframe(padapter, pmgntframe);
2715         return;
2716 }
2717
2718 void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
2719 {
2720         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2721         u8 action = P2P_PUB_ACTION_ACTION;
2722         __be32                  p2poui = cpu_to_be32(P2POUI);
2723         u8 oui_subtype = P2P_INVIT_REQ;
2724         u8 p2pie[255] = { 0x00 };
2725         u8 p2pielen = 0;
2726         u8 dialogToken = 3;
2727         u16 len_channellist_attr = 0;
2728         struct xmit_frame                       *pmgntframe;
2729         struct pkt_attrib                       *pattrib;
2730         unsigned char                                   *pframe;
2731         struct rtw_ieee80211_hdr        *pwlanhdr;
2732         __le16 *fctrl;
2733         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2734         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2735         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2736
2737         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2738         if (pmgntframe == NULL)
2739                 return;
2740
2741         /* update attribute */
2742         pattrib = &pmgntframe->attrib;
2743         update_mgntframe_attrib(padapter, pattrib);
2744
2745         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2746
2747         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2748         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2749
2750         fctrl = &(pwlanhdr->frame_ctl);
2751         *(fctrl) = 0;
2752
2753         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2754         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2755         memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
2756
2757         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2758         pmlmeext->mgnt_seq++;
2759         SetFrameSubType(pframe, WIFI_ACTION);
2760
2761         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2762         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2763
2764         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2765         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2766         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
2767         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2768         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
2769
2770         /*      P2P IE Section. */
2771
2772         /*      P2P OUI */
2773         p2pielen = 0;
2774         p2pie[p2pielen++] = 0x50;
2775         p2pie[p2pielen++] = 0x6F;
2776         p2pie[p2pielen++] = 0x9A;
2777         p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
2778
2779         /*      Commented by Albert 20101011 */
2780         /*      According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
2781         /*      1. Configuration Timeout */
2782         /*      2. Invitation Flags */
2783         /*      3. Operating Channel    (Only GO) */
2784         /*      4. P2P Group BSSID      (Should be included if I am the GO) */
2785         /*      5. Channel List */
2786         /*      6. P2P Group ID */
2787         /*      7. P2P Device Info */
2788
2789         /*      Configuration Timeout */
2790         /*      Type: */
2791         p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2792
2793         /*      Length: */
2794         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2795         p2pielen += 2;
2796
2797         /*      Value: */
2798         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
2799         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
2800
2801         /*      Invitation Flags */
2802         /*      Type: */
2803         p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
2804
2805         /*      Length: */
2806         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2807         p2pielen += 2;
2808
2809         /*      Value: */
2810         p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
2811
2812
2813         /*      Operating Channel */
2814         /*      Type: */
2815         p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2816
2817         /*      Length: */
2818         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2819         p2pielen += 2;
2820
2821         /*      Value: */
2822         /*      Country String */
2823         p2pie[p2pielen++] = 'X';
2824         p2pie[p2pielen++] = 'X';
2825
2826         /*      The third byte should be set to 0x04. */
2827         /*      Described in the "Operating Channel Attribute" section. */
2828         p2pie[p2pielen++] = 0x04;
2829
2830         /*      Operating Class */
2831         p2pie[p2pielen++] = 0x51;
2832
2833         /*      Channel Number */
2834         p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;       /*      operating channel number */
2835
2836         if (_rtw_memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
2837                 /*      P2P Group BSSID */
2838                 /*      Type: */
2839                 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
2840
2841                 /*      Length: */
2842                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2843                 p2pielen += 2;
2844
2845                 /*      Value: */
2846                 /*      P2P Device Address for GO */
2847                 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2848                 p2pielen += ETH_ALEN;
2849         }
2850
2851         /*      Channel List */
2852         /*      Type: */
2853         p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2854
2855
2856         /*      Length: */
2857         /*  Country String(3) */
2858         /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2859         /*  + number of channels in all classes */
2860         len_channellist_attr = 3
2861            + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2862            + get_reg_classes_full_count(&pmlmeext->channel_list);
2863
2864         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2865
2866         p2pielen += 2;
2867
2868         /*      Value: */
2869         /*      Country String */
2870         p2pie[p2pielen++] = 'X';
2871         p2pie[p2pielen++] = 'X';
2872
2873         /*      The third byte should be set to 0x04. */
2874         /*      Described in the "Operating Channel Attribute" section. */
2875         p2pie[p2pielen++] = 0x04;
2876
2877         /*      Channel Entry List */
2878         {
2879                 int i, j;
2880                 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2881                         /*      Operating Class */
2882                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2883
2884                         /*      Number of Channels */
2885                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2886
2887                         /*      Channel List */
2888                         for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2889                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2890                         }
2891                 }
2892         }
2893
2894
2895         /*      P2P Group ID */
2896         /*      Type: */
2897         p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2898
2899         /*      Length: */
2900         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
2901         p2pielen += 2;
2902
2903         /*      Value: */
2904         /*      P2P Device Address for GO */
2905         memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2906         p2pielen += ETH_ALEN;
2907
2908         /*      SSID */
2909         memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
2910         p2pielen += pwdinfo->invitereq_info.ssidlen;
2911
2912
2913         /*      Device Info */
2914         /*      Type: */
2915         p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2916
2917         /*      Length: */
2918         /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2919         /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2920         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2921         p2pielen += 2;
2922
2923         /*      Value: */
2924         /*      P2P Device Address */
2925         memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2926         p2pielen += ETH_ALEN;
2927
2928         /*      Config Method */
2929         /*      This field should be big endian. Noted by P2P specification. */
2930         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
2931         p2pielen += 2;
2932
2933         /*      Primary Device Type */
2934         /*      Category ID */
2935         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2936         p2pielen += 2;
2937
2938         /*      OUI */
2939         *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2940         p2pielen  += 4;
2941
2942         /*      Sub Category ID */
2943         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2944         p2pielen += 2;
2945
2946         /*      Number of Secondary Device Types */
2947         p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
2948
2949         /*      Device Name */
2950         /*      Type: */
2951         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2952         p2pielen += 2;
2953
2954         /*      Length: */
2955         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2956         p2pielen += 2;
2957
2958         /*      Value: */
2959         memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2960         p2pielen += pwdinfo->device_name_len;
2961
2962         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2963
2964         pattrib->last_txcmdsz = pattrib->pktlen;
2965
2966         dump_mgntframe(padapter, pmgntframe);
2967
2968         return;
2969 }
2970
2971 void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
2972 {
2973         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2974         u8 action = P2P_PUB_ACTION_ACTION;
2975         __be32                  p2poui = cpu_to_be32(P2POUI);
2976         u8 oui_subtype = P2P_INVIT_RESP;
2977         u8 p2pie[255] = { 0x00 };
2978         u8 p2pielen = 0;
2979         u16 len_channellist_attr = 0;
2980         struct xmit_frame                       *pmgntframe;
2981         struct pkt_attrib                       *pattrib;
2982         unsigned char                                   *pframe;
2983         struct rtw_ieee80211_hdr        *pwlanhdr;
2984         __le16 *fctrl;
2985         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2986         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2987         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2988
2989         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2990         if (pmgntframe == NULL)
2991                 return;
2992
2993         /* update attribute */
2994         pattrib = &pmgntframe->attrib;
2995         update_mgntframe_attrib(padapter, pattrib);
2996
2997         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2998
2999         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3000         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3001
3002         fctrl = &(pwlanhdr->frame_ctl);
3003         *(fctrl) = 0;
3004
3005         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3006         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3007         memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
3008
3009         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3010         pmlmeext->mgnt_seq++;
3011         SetFrameSubType(pframe, WIFI_ACTION);
3012
3013         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3014         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3015
3016         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3017         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3018         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
3019         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3020         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
3021
3022         /*      P2P IE Section. */
3023
3024         /*      P2P OUI */
3025         p2pielen = 0;
3026         p2pie[p2pielen++] = 0x50;
3027         p2pie[p2pielen++] = 0x6F;
3028         p2pie[p2pielen++] = 0x9A;
3029         p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
3030
3031         /*      Commented by Albert 20101005 */
3032         /*      According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
3033         /*      1. Status */
3034         /*      2. Configuration Timeout */
3035         /*      3. Operating Channel    (Only GO) */
3036         /*      4. P2P Group BSSID      (Only GO) */
3037         /*      5. Channel List */
3038
3039         /*      P2P Status */
3040         /*      Type: */
3041         p2pie[p2pielen++] = P2P_ATTR_STATUS;
3042
3043         /*      Length: */
3044         *(__le16  *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
3045         p2pielen += 2;
3046
3047         /*      Value: */
3048         /*      When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
3049         /*      Sent the event receiving the P2P Invitation Req frame to DMP UI. */
3050         /*      DMP had to compare the MAC address to find out the profile. */
3051         /*      So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
3052         /*      If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
3053         /*      to NB to rebuild the persistent group. */
3054         p2pie[p2pielen++] = status_code;
3055
3056         /*      Configuration Timeout */
3057         /*      Type: */
3058         p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
3059
3060         /*      Length: */
3061         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
3062         p2pielen += 2;
3063
3064         /*      Value: */
3065         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
3066         p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
3067
3068         if (status_code == P2P_STATUS_SUCCESS) {
3069                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3070                         /*      The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
3071                         /*      In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
3072                         /*      First one is operating channel attribute. */
3073                         /*      Second one is P2P Group BSSID attribute. */
3074
3075                         /*      Operating Channel */
3076                         /*      Type: */
3077                         p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3078
3079                         /*      Length: */
3080                         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3081                         p2pielen += 2;
3082
3083                         /*      Value: */
3084                         /*      Country String */
3085                         p2pie[p2pielen++] = 'X';
3086                         p2pie[p2pielen++] = 'X';
3087
3088                         /*      The third byte should be set to 0x04. */
3089                         /*      Described in the "Operating Channel Attribute" section. */
3090                         p2pie[p2pielen++] = 0x04;
3091
3092                         /*      Operating Class */
3093                         p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
3094
3095                         /*      Channel Number */
3096                         p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
3097
3098
3099                         /*      P2P Group BSSID */
3100                         /*      Type: */
3101                         p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
3102
3103                         /*      Length: */
3104                         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
3105                         p2pielen += 2;
3106
3107                         /*      Value: */
3108                         /*      P2P Device Address for GO */
3109                         memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
3110                         p2pielen += ETH_ALEN;
3111                 }
3112
3113                 /*      Channel List */
3114                 /*      Type: */
3115                 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3116
3117                 /*      Length: */
3118                 /*  Country String(3) */
3119                 /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
3120                 /*  + number of channels in all classes */
3121                 len_channellist_attr = 3
3122                         + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
3123                         + get_reg_classes_full_count(&pmlmeext->channel_list);
3124
3125                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
3126                 p2pielen += 2;
3127
3128                 /*      Value: */
3129                 /*      Country String */
3130                 p2pie[p2pielen++] = 'X';
3131                 p2pie[p2pielen++] = 'X';
3132
3133                 /*      The third byte should be set to 0x04. */
3134                 /*      Described in the "Operating Channel Attribute" section. */
3135                 p2pie[p2pielen++] = 0x04;
3136
3137                 /*      Channel Entry List */
3138                 {
3139                         int i, j;
3140                         for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3141                                 /*      Operating Class */
3142                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3143
3144                                 /*      Number of Channels */
3145                                 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3146
3147                                 /*      Channel List */
3148                                 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3149                                         p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3150                                 }
3151                         }
3152                 }
3153         }
3154
3155         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
3156
3157         pattrib->last_txcmdsz = pattrib->pktlen;
3158
3159         dump_mgntframe(padapter, pmgntframe);
3160
3161         return;
3162 }
3163
3164 void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
3165 {
3166         unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3167         u8 action = P2P_PUB_ACTION_ACTION;
3168         u8 dialogToken = 1;
3169         u8 oui_subtype = P2P_PROVISION_DISC_REQ;
3170         u8 wpsie[100] = { 0x00 };
3171         u8 wpsielen = 0;
3172         __be32 p2poui = cpu_to_be32(P2POUI);
3173         u32                     p2pielen = 0;
3174         struct xmit_frame                       *pmgntframe;
3175         struct pkt_attrib                       *pattrib;
3176         unsigned char                                   *pframe;
3177         struct rtw_ieee80211_hdr        *pwlanhdr;
3178         __le16 *fctrl;
3179         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3180         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3181         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3182
3183         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3184         if (pmgntframe == NULL)
3185                 return;
3186
3187         DBG_88E("[%s] In\n", __func__);
3188         /* update attribute */
3189         pattrib = &pmgntframe->attrib;
3190         update_mgntframe_attrib(padapter, pattrib);
3191
3192         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3193
3194         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3195         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3196
3197         fctrl = &(pwlanhdr->frame_ctl);
3198         *(fctrl) = 0;
3199
3200         memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
3201         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3202         memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
3203
3204         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3205         pmlmeext->mgnt_seq++;
3206         SetFrameSubType(pframe, WIFI_ACTION);
3207
3208         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3209         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3210
3211         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3212         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3213         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
3214         pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3215         pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
3216
3217         p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
3218
3219         pframe += p2pielen;
3220         pattrib->pktlen += p2pielen;
3221
3222         wpsielen = 0;
3223         /*      WPS OUI */
3224         *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3225         wpsielen += 4;
3226
3227         /*      WPS version */
3228         /*      Type: */
3229         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3230         wpsielen += 2;
3231
3232         /*      Length: */
3233         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3234         wpsielen += 2;
3235
3236         /*      Value: */
3237         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3238
3239         /*      Config Method */
3240         /*      Type: */
3241         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3242         wpsielen += 2;
3243
3244         /*      Length: */
3245         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3246         wpsielen += 2;
3247
3248         /*      Value: */
3249         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3250         wpsielen += 2;
3251
3252         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3253
3254         pattrib->last_txcmdsz = pattrib->pktlen;
3255
3256         dump_mgntframe(padapter, pmgntframe);
3257
3258         return;
3259 }
3260
3261 static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
3262 {
3263         u8 i, match_result = 0;
3264
3265         DBG_88E("[%s] peermac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
3266                 peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]);
3267
3268         for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
3269                DBG_88E("[%s] profileinfo_mac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
3270                             profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2], profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]);
3271                 if (_rtw_memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
3272                         match_result = 1;
3273                         DBG_88E("[%s] Match!\n", __func__);
3274                         break;
3275                 }
3276         }
3277         return match_result;
3278 }
3279
3280 void issue_probersp_p2p(struct adapter *padapter, unsigned char *da)
3281 {
3282         struct xmit_frame                       *pmgntframe;
3283         struct pkt_attrib                       *pattrib;
3284         unsigned char                                   *pframe;
3285         struct rtw_ieee80211_hdr        *pwlanhdr;
3286         __le16 *fctrl;
3287         unsigned char                                   *mac;
3288         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3289         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3290         u16 beacon_interval = 100;
3291         u16 capInfo = 0;
3292         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3293         u8 wpsie[255] = { 0x00 };
3294         u32                                     wpsielen = 0, p2pielen = 0;
3295
3296         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3297         if (pmgntframe == NULL)
3298                 return;
3299
3300         /* update attribute */
3301         pattrib = &pmgntframe->attrib;
3302         update_mgntframe_attrib(padapter, pattrib);
3303
3304         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3305
3306         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3307         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3308
3309         mac = myid(&(padapter->eeprompriv));
3310
3311         fctrl = &(pwlanhdr->frame_ctl);
3312         *(fctrl) = 0;
3313         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3314         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3315
3316         /*      Use the device address for BSSID field. */
3317         memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
3318
3319         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3320         pmlmeext->mgnt_seq++;
3321         SetFrameSubType(fctrl, WIFI_PROBERSP);
3322
3323         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3324         pattrib->pktlen = pattrib->hdrlen;
3325         pframe += pattrib->hdrlen;
3326
3327         /* timestamp will be inserted by hardware */
3328         pframe += 8;
3329         pattrib->pktlen += 8;
3330
3331         /*  beacon interval: 2 bytes */
3332         memcpy(pframe, (unsigned char *)&beacon_interval, 2);
3333         pframe += 2;
3334         pattrib->pktlen += 2;
3335
3336         /*      capability info: 2 bytes */
3337         /*      ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
3338         capInfo |= cap_ShortPremble;
3339         capInfo |= cap_ShortSlot;
3340
3341         memcpy(pframe, (unsigned char *)&capInfo, 2);
3342         pframe += 2;
3343         pattrib->pktlen += 2;
3344
3345
3346         /*  SSID */
3347         pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
3348
3349         /*  supported rates... */
3350         /*      Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3351         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3352
3353         /*  DS parameter set */
3354         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
3355
3356         /*      Todo: WPS IE */
3357         /*      Noted by Albert 20100907 */
3358         /*      According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3359
3360         wpsielen = 0;
3361         /*      WPS OUI */
3362         *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3363         wpsielen += 4;
3364
3365         /*      WPS version */
3366         /*      Type: */
3367         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3368         wpsielen += 2;
3369
3370         /*      Length: */
3371         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3372         wpsielen += 2;
3373
3374         /*      Value: */
3375         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3376
3377         /*      WiFi Simple Config State */
3378         /*      Type: */
3379         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
3380         wpsielen += 2;
3381
3382         /*      Length: */
3383         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3384         wpsielen += 2;
3385
3386         /*      Value: */
3387         wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;   /*      Not Configured. */
3388
3389         /*      Response Type */
3390         /*      Type: */
3391         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
3392         wpsielen += 2;
3393
3394         /*      Length: */
3395         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3396         wpsielen += 2;
3397
3398         /*      Value: */
3399         wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
3400
3401         /*      UUID-E */
3402         /*      Type: */
3403         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3404         wpsielen += 2;
3405
3406         /*      Length: */
3407         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3408         wpsielen += 2;
3409
3410         /*      Value: */
3411         memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3412         wpsielen += 0x10;
3413
3414         /*      Manufacturer */
3415         /*      Type: */
3416         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
3417         wpsielen += 2;
3418
3419         /*      Length: */
3420         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
3421         wpsielen += 2;
3422
3423         /*      Value: */
3424         memcpy(wpsie + wpsielen, "Realtek", 7);
3425         wpsielen += 7;
3426
3427         /*      Model Name */
3428         /*      Type: */
3429         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
3430         wpsielen += 2;
3431
3432         /*      Length: */
3433         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
3434         wpsielen += 2;
3435
3436         /*      Value: */
3437         memcpy(wpsie + wpsielen, "8188EU", 6);
3438         wpsielen += 6;
3439
3440         /*      Model Number */
3441         /*      Type: */
3442         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
3443         wpsielen += 2;
3444
3445         /*      Length: */
3446         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3447         wpsielen += 2;
3448
3449         /*      Value: */
3450         wpsie[wpsielen++] = 0x31;               /*      character 1 */
3451
3452         /*      Serial Number */
3453         /*      Type: */
3454         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
3455         wpsielen += 2;
3456
3457         /*      Length: */
3458         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
3459         wpsielen += 2;
3460
3461         /*      Value: */
3462         memcpy(wpsie + wpsielen, "123456" , ETH_ALEN);
3463         wpsielen += ETH_ALEN;
3464
3465         /*      Primary Device Type */
3466         /*      Type: */
3467         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3468         wpsielen += 2;
3469
3470         /*      Length: */
3471         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3472         wpsielen += 2;
3473
3474         /*      Value: */
3475         /*      Category ID */
3476         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
3477         wpsielen += 2;
3478
3479         /*      OUI */
3480         *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3481         wpsielen += 4;
3482
3483         /*      Sub Category ID */
3484         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
3485         wpsielen += 2;
3486
3487         /*      Device Name */
3488         /*      Type: */
3489         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3490         wpsielen += 2;
3491
3492         /*      Length: */
3493         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3494         wpsielen += 2;
3495
3496         /*      Value: */
3497         if (pwdinfo->device_name_len) {
3498                 memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3499                 wpsielen += pwdinfo->device_name_len;
3500         }
3501
3502         /*      Config Method */
3503         /*      Type: */
3504         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3505         wpsielen += 2;
3506
3507         /*      Length: */
3508         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3509         wpsielen += 2;
3510
3511         /*      Value: */
3512         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3513         wpsielen += 2;
3514
3515
3516         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3517
3518
3519         p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
3520         pframe += p2pielen;
3521         pattrib->pktlen += p2pielen;
3522
3523         pattrib->last_txcmdsz = pattrib->pktlen;
3524
3525         dump_mgntframe(padapter, pmgntframe);
3526
3527         return;
3528 }
3529
3530 static int _issue_probereq_p2p(struct adapter *padapter, u8 *da, int wait_ack)
3531 {
3532         int ret = _FAIL;
3533         struct xmit_frame               *pmgntframe;
3534         struct pkt_attrib               *pattrib;
3535         unsigned char                   *pframe;
3536         struct rtw_ieee80211_hdr        *pwlanhdr;
3537         __le16 *fctrl;
3538         unsigned char                   *mac;
3539         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3540         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3541         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3542         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3543         u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
3544         u16 wpsielen = 0, p2pielen = 0;
3545         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3546
3547         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3548         if (pmgntframe == NULL)
3549                 goto exit;
3550
3551         /* update attribute */
3552         pattrib = &pmgntframe->attrib;
3553         update_mgntframe_attrib(padapter, pattrib);
3554
3555
3556         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3557
3558         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3559         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3560
3561         mac = myid(&(padapter->eeprompriv));
3562
3563         fctrl = &(pwlanhdr->frame_ctl);
3564         *(fctrl) = 0;
3565
3566         if (da) {
3567                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3568                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
3569         } else {
3570                 if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
3571                         /*      This two flags will be set when this is only the P2P client mode. */
3572                         memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3573                         memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3574                 } else {
3575                         /*      broadcast probe request frame */
3576                         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
3577                         memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
3578                 }
3579         }
3580         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3581
3582         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3583         pmlmeext->mgnt_seq++;
3584         SetFrameSubType(pframe, WIFI_PROBEREQ);
3585
3586         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
3587         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
3588
3589         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3590                 pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
3591         else
3592                 pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
3593
3594         /*      Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
3595         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3596
3597
3598         /*      WPS IE */
3599         /*      Noted by Albert 20110221 */
3600         /*      According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3601
3602         wpsielen = 0;
3603         /*      WPS OUI */
3604         *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3605         wpsielen += 4;
3606
3607         /*      WPS version */
3608         /*      Type: */
3609         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3610         wpsielen += 2;
3611
3612         /*      Length: */
3613         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3614         wpsielen += 2;
3615
3616         /*      Value: */
3617         wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3618
3619         if (pmlmepriv->wps_probe_req_ie == NULL) {
3620                 /*      UUID-E */
3621                 /*      Type: */
3622                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3623                 wpsielen += 2;
3624
3625                 /*      Length: */
3626                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3627                 wpsielen += 2;
3628
3629                 /*      Value: */
3630                 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3631                 wpsielen += 0x10;
3632
3633                 /*      Config Method */
3634                 /*      Type: */
3635                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3636                 wpsielen += 2;
3637
3638                 /*      Length: */
3639                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3640                 wpsielen += 2;
3641
3642                 /*      Value: */
3643                 *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3644                 wpsielen += 2;
3645         }
3646
3647         /*      Device Name */
3648         /*      Type: */
3649         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3650         wpsielen += 2;
3651
3652         /*      Length: */
3653         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3654         wpsielen += 2;
3655
3656         /*      Value: */
3657         memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3658         wpsielen += pwdinfo->device_name_len;
3659
3660         /*      Primary Device Type */
3661         /*      Type: */
3662         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3663         wpsielen += 2;
3664
3665         /*      Length: */
3666         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3667         wpsielen += 2;
3668
3669         /*      Value: */
3670         /*      Category ID */
3671         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
3672         wpsielen += 2;
3673
3674         /*      OUI */
3675         *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3676         wpsielen += 4;
3677
3678         /*      Sub Category ID */
3679         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
3680         wpsielen += 2;
3681
3682         /*      Device Password ID */
3683         /*      Type: */
3684         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
3685         wpsielen += 2;
3686
3687         /*      Length: */
3688         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3689         wpsielen += 2;
3690
3691         /*      Value: */
3692         *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);   /*      Registrar-specified */
3693         wpsielen += 2;
3694
3695         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3696
3697         /*      P2P OUI */
3698         p2pielen = 0;
3699         p2pie[p2pielen++] = 0x50;
3700         p2pie[p2pielen++] = 0x6F;
3701         p2pie[p2pielen++] = 0x9A;
3702         p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
3703
3704         /*      Commented by Albert 20110221 */
3705         /*      According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
3706         /*      1. P2P Capability */
3707         /*      2. P2P Device ID if this probe request wants to find the specific P2P device */
3708         /*      3. Listen Channel */
3709         /*      4. Extended Listen Timing */
3710         /*      5. Operating Channel if this WiFi is working as the group owner now */
3711
3712         /*      P2P Capability */
3713         /*      Type: */
3714         p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
3715
3716         /*      Length: */
3717         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
3718         p2pielen += 2;
3719
3720         /*      Value: */
3721         /*      Device Capability Bitmap, 1 byte */
3722         p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
3723
3724         /*      Group Capability Bitmap, 1 byte */
3725         if (pwdinfo->persistent_supported)
3726                 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
3727         else
3728                 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
3729
3730         /*      Listen Channel */
3731         /*      Type: */
3732         p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
3733
3734         /*      Length: */
3735         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3736         p2pielen += 2;
3737
3738         /*      Value: */
3739         /*      Country String */
3740         p2pie[p2pielen++] = 'X';
3741         p2pie[p2pielen++] = 'X';
3742
3743         /*      The third byte should be set to 0x04. */
3744         /*      Described in the "Operating Channel Attribute" section. */
3745         p2pie[p2pielen++] = 0x04;
3746
3747         /*      Operating Class */
3748         p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
3749
3750         /*      Channel Number */
3751         p2pie[p2pielen++] = pwdinfo->listen_channel;    /*      listen channel */
3752
3753
3754         /*      Extended Listen Timing */
3755         /*      Type: */
3756         p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
3757
3758         /*      Length: */
3759         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
3760         p2pielen += 2;
3761
3762         /*      Value: */
3763         /*      Availability Period */
3764         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3765         p2pielen += 2;
3766
3767         /*      Availability Interval */
3768         *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3769         p2pielen += 2;
3770
3771         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3772                 /*      Operating Channel (if this WiFi is working as the group owner now) */
3773                 /*      Type: */
3774                 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3775
3776                 /*      Length: */
3777                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3778                 p2pielen += 2;
3779
3780                 /*      Value: */
3781                 /*      Country String */
3782                 p2pie[p2pielen++] = 'X';
3783                 p2pie[p2pielen++] = 'X';
3784
3785                 /*      The third byte should be set to 0x04. */
3786                 /*      Described in the "Operating Channel Attribute" section. */
3787                 p2pie[p2pielen++] = 0x04;
3788
3789                 /*      Operating Class */
3790                 p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
3791
3792                 /*      Channel Number */
3793                 p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
3794         }
3795
3796         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
3797
3798         if (pmlmepriv->wps_probe_req_ie != NULL) {
3799                 /* WPS IE */
3800                 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
3801                 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
3802                 pframe += pmlmepriv->wps_probe_req_ie_len;
3803         }
3804
3805         pattrib->last_txcmdsz = pattrib->pktlen;
3806
3807         RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
3808
3809         if (wait_ack) {
3810                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3811         } else {
3812                 dump_mgntframe(padapter, pmgntframe);
3813                 ret = _SUCCESS;
3814         }
3815
3816 exit:
3817         return ret;
3818 }
3819
3820 inline void issue_probereq_p2p(struct adapter *adapter, u8 *da)
3821 {
3822         _issue_probereq_p2p(adapter, da, false);
3823 }
3824
3825 int issue_probereq_p2p_ex(struct adapter *adapter, u8 *da, int try_cnt, int wait_ms)
3826 {
3827         int ret;
3828         int i = 0;
3829         u32 start = rtw_get_current_time();
3830
3831         do {
3832                 ret = _issue_probereq_p2p(adapter, da, wait_ms > 0 ? true : false);
3833
3834                 i++;
3835
3836                 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
3837                         break;
3838
3839                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3840                         rtw_msleep_os(wait_ms);
3841         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3842
3843         if (ret != _FAIL) {
3844                 ret = _SUCCESS;
3845                 goto exit;
3846         }
3847
3848         if (try_cnt && wait_ms) {
3849                 if (da)
3850                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
3851                                 FUNC_ADPT_ARG(adapter), da, rtw_get_oper_ch(adapter),
3852                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
3853                 else
3854                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3855                                 FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
3856                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
3857         }
3858 exit:
3859         return ret;
3860 }
3861
3862 #endif /* CONFIG_88EU_P2P */
3863
3864 static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
3865 {
3866         struct adapter *adapter = recv_frame->u.hdr.adapter;
3867         struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
3868         u8 *frame = recv_frame->u.hdr.rx_data;
3869         u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
3870                 (recv_frame->u.hdr.attrib.frag_num & 0xf);
3871
3872         if (GetRetry(frame)) {
3873                 if (token >= 0) {
3874                         if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) {
3875                                 DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
3876                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
3877                                 return _FAIL;
3878                         }
3879                 } else {
3880                         if (seq_ctrl == mlmeext->action_public_rxseq) {
3881                                 DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
3882                                         FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
3883                                 return _FAIL;
3884                         }
3885                 }
3886         }
3887
3888         mlmeext->action_public_rxseq = seq_ctrl;
3889
3890         if (token >= 0)
3891                 mlmeext->action_public_dialog_token = token;
3892
3893         return _SUCCESS;
3894 }
3895
3896 static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
3897 {
3898         u8 *pframe = precv_frame->u.hdr.rx_data;
3899         u8 *frame_body;
3900         u8 dialogToken = 0;
3901 #ifdef CONFIG_88EU_P2P
3902         struct adapter *padapter = precv_frame->u.hdr.adapter;
3903         uint len = precv_frame->u.hdr.len;
3904         u8 *p2p_ie;
3905         u32     p2p_ielen;
3906         struct  wifidirect_info *pwdinfo = &(padapter->wdinfo);
3907         u8      result = P2P_STATUS_SUCCESS;
3908         u8      empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3909 #endif /* CONFIG_88EU_P2P */
3910
3911         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3912
3913         dialogToken = frame_body[7];
3914
3915         if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
3916                 return _FAIL;
3917
3918 #ifdef CONFIG_88EU_P2P
3919         _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
3920         /*      Do nothing if the driver doesn't enable the P2P function. */
3921         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
3922                 return _SUCCESS;
3923
3924         len -= sizeof(struct rtw_ieee80211_hdr_3addr);
3925
3926         switch (frame_body[6]) { /* OUI Subtype */
3927         case P2P_GO_NEGO_REQ:
3928                 DBG_88E("[%s] Got GO Nego Req Frame\n", __func__);
3929                 _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3930
3931                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
3932                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3933
3934                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
3935                         /*      Commented by Albert 20110526 */
3936                         /*      In this case, this means the previous nego fail doesn't be reset yet. */
3937                         _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3938                         /*      Restore the previous p2p state */
3939                         rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3940                         DBG_88E("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
3941                 }
3942
3943                 /*      Commented by Kurt 20110902 */
3944                 /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
3945                 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3946                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3947
3948                 /*      Commented by Kurt 20120113 */
3949                 /*      Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
3950                 if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
3951                         memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
3952
3953                 result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
3954                 issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result);
3955
3956                 /*      Commented by Albert 20110718 */
3957                 /*      No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
3958                 _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3959                 break;
3960         case P2P_GO_NEGO_RESP:
3961                 DBG_88E("[%s] Got GO Nego Resp Frame\n", __func__);
3962
3963                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
3964                         /*      Commented by Albert 20110425 */
3965                         /*      The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
3966                         _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3967                         pwdinfo->nego_req_info.benable = false;
3968                         result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
3969                         issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result);
3970                         if (P2P_STATUS_SUCCESS == result) {
3971                                 if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3972                                         pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3973                                         pwdinfo->p2p_info.scan_op_ch_only = 1;
3974                                         _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3975                                 }
3976                         }
3977                         /*      Reset the dialog token for group negotiation frames. */
3978                         pwdinfo->negotiation_dialog_token = 1;
3979                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3980                                 _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3981                 } else {
3982                         DBG_88E("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
3983                 }
3984                 break;
3985         case P2P_GO_NEGO_CONF:
3986                 DBG_88E("[%s] Got GO Nego Confirm Frame\n", __func__);
3987                 result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
3988                 if (P2P_STATUS_SUCCESS == result) {
3989                         if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3990                                 pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3991                                 pwdinfo->p2p_info.scan_op_ch_only = 1;
3992                                 _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3993                         }
3994                 }
3995                 break;
3996         case P2P_INVIT_REQ:
3997                 /*      Added by Albert 2010/10/05 */
3998                 /*      Received the P2P Invite Request frame. */
3999
4000                 DBG_88E("[%s] Got invite request frame!\n", __func__);
4001                 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
4002                 if (p2p_ie) {
4003                         /*      Parse the necessary information from the P2P Invitation Request frame. */
4004                         /*      For example: The MAC address of sending this P2P Invitation Request frame. */
4005                         u32     attr_contentlen = 0;
4006                         u8      status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4007                         struct group_id_info group_id;
4008                         u8      invitation_flag = 0;
4009
4010                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
4011                         if (attr_contentlen) {
4012                                 rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
4013                                 /*      Commented by Albert 20120510 */
4014                                 /*      Copy to the pwdinfo->p2p_peer_interface_addr. */
4015                                 /*      So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
4016                                 /*      #> iwpriv wlan0 p2p_get peer_ifa */
4017                                 /*      After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
4018
4019                                 if (attr_contentlen) {
4020                                         DBG_88E("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
4021                                                 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
4022                                                 pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
4023                                                 pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4024                                 }
4025
4026                                 if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
4027                                         /*      Re-invoke the persistent group. */
4028
4029                                         _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
4030                                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
4031                                         if (attr_contentlen) {
4032                                                 if (_rtw_memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
4033                                                         /*      The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
4034                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
4035                                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4036                                                         status_code = P2P_STATUS_SUCCESS;
4037                                                 } else {
4038                                                         /*      The p2p device sending this p2p invitation request wants to be the persistent GO. */
4039                                                         if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
4040                                                                 u8 operatingch_info[5] = { 0x00 };
4041                                                                 if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
4042                                                                         if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) {
4043                                                                                 /*      The operating channel is acceptable for this device. */
4044                                                                                 pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
4045                                                                                 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
4046                                                                                 _set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
4047                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4048                                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4049                                                                                 status_code = P2P_STATUS_SUCCESS;
4050                                                                         } else {
4051                                                                                 /*      The operating channel isn't supported by this device. */
4052                                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4053                                                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4054                                                                                 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
4055                                                                                 _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
4056                                                                         }
4057                                                                 } else {
4058                                                                         /*      Commented by Albert 20121130 */
4059                                                                         /*      Intel will use the different P2P IE to store the operating channel information */
4060                                                                         /*      Workaround for Intel WiDi 3.5 */
4061                                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4062                                                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4063                                                                         status_code = P2P_STATUS_SUCCESS;
4064                                                                 }
4065                                                         } else {
4066                                                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4067                                                                 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
4068                                                         }
4069                                                 }
4070                                         } else {
4071                                                 DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4072                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4073                                         }
4074                                 } else {
4075                                         /*      Received the invitation to join a P2P group. */
4076
4077                                         _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
4078                                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
4079                                         if (attr_contentlen) {
4080                                                 if (_rtw_memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
4081                                                         /*      In this case, the GO can't be myself. */
4082                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4083                                                         status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4084                                                 } else {
4085                                                         /*      The p2p device sending this p2p invitation request wants to join an existing P2P group */
4086                                                         /*      Commented by Albert 2012/06/28 */
4087                                                         /*      In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
4088                                                         /*      The peer device address should be the destination address for the provisioning discovery request. */
4089                                                         /*      Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
4090                                                         /*      The peer interface address should be the address for WPS mac address */
4091                                                         memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN);
4092                                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4093                                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
4094                                                         status_code = P2P_STATUS_SUCCESS;
4095                                                 }
4096                                         } else {
4097                                                 DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4098                                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4099                                         }
4100                                 }
4101                         } else {
4102                                 DBG_88E("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
4103                                 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4104                         }
4105
4106                         DBG_88E("[%s] status_code = %d\n", __func__, status_code);
4107
4108                         pwdinfo->inviteresp_info.token = frame_body[7];
4109                         issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
4110                 }
4111                 break;
4112         case P2P_INVIT_RESP: {
4113                 u8      attr_content = 0x00;
4114                 u32     attr_contentlen = 0;
4115
4116                 DBG_88E("[%s] Got invite response frame!\n", __func__);
4117                 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
4118                 p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
4119                 if (p2p_ie) {
4120                         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
4121
4122                         if (attr_contentlen == 1) {
4123                                 DBG_88E("[%s] Status = %d\n", __func__, attr_content);
4124                                 pwdinfo->invitereq_info.benable = false;
4125
4126                                 if (attr_content == P2P_STATUS_SUCCESS) {
4127                                         if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
4128                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4129                                         } else {
4130                                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4131                                         }
4132                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
4133                                 } else {
4134                                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4135                                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4136                                 }
4137                         } else {
4138                                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4139                                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4140                         }
4141                 } else {
4142                         rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4143                         rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4144                 }
4145
4146                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
4147                         _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
4148                 break;
4149         }
4150         case P2P_DEVDISC_REQ:
4151                 process_p2p_devdisc_req(pwdinfo, pframe, len);
4152                 break;
4153         case P2P_DEVDISC_RESP:
4154                 process_p2p_devdisc_resp(pwdinfo, pframe, len);
4155                 break;
4156         case P2P_PROVISION_DISC_REQ:
4157                 DBG_88E("[%s] Got Provisioning Discovery Request Frame\n", __func__);
4158                 process_p2p_provdisc_req(pwdinfo, pframe, len);
4159                 memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
4160
4161                 /* 20110902 Kurt */
4162                 /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
4163                 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
4164                         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4165
4166                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
4167                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
4168                 break;
4169         case P2P_PROVISION_DISC_RESP:
4170                 /*      Commented by Albert 20110707 */
4171                 /*      Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
4172                 DBG_88E("[%s] Got Provisioning Discovery Response Frame\n", __func__);
4173                 /*      Commented by Albert 20110426 */
4174                 /*      The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
4175                 _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
4176                 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
4177                 process_p2p_provdisc_resp(pwdinfo, pframe);
4178                 _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
4179                 break;
4180         }
4181 #endif /* CONFIG_88EU_P2P */
4182
4183         return _SUCCESS;
4184 }
4185
4186 static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
4187 {
4188         unsigned int ret = _FAIL;
4189         u8 *pframe = precv_frame->u.hdr.rx_data;
4190         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
4191
4192         if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == true) {
4193                 ret = on_action_public_p2p(precv_frame);
4194         }
4195
4196         return ret;
4197 }
4198
4199 static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
4200 {
4201         unsigned int ret = _FAIL;
4202         u8 *pframe = precv_frame->u.hdr.rx_data;
4203         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
4204         u8 token;
4205
4206         token = frame_body[2];
4207
4208         if (rtw_action_public_decache(precv_frame, token) == _FAIL)
4209                 goto exit;
4210
4211         ret = _SUCCESS;
4212
4213 exit:
4214         return ret;
4215 }
4216
4217 unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
4218 {
4219         unsigned int ret = _FAIL;
4220         u8 *pframe = precv_frame->u.hdr.rx_data;
4221         u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
4222         u8 category, action;
4223
4224         /* check RA matches or not */
4225         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
4226                 goto exit;
4227
4228         category = frame_body[0];
4229         if (category != RTW_WLAN_CATEGORY_PUBLIC)
4230                 goto exit;
4231
4232         action = frame_body[1];
4233         switch (action) {
4234         case ACT_PUBLIC_VENDOR:
4235                 ret = on_action_public_vendor(precv_frame);
4236                 break;
4237         default:
4238                 ret = on_action_public_default(precv_frame, action);
4239                 break;
4240         }
4241
4242 exit:
4243         return ret;
4244 }
4245
4246 unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
4247 {
4248         return _SUCCESS;
4249 }
4250
4251 unsigned int OnAction_wmm(struct adapter *padapter, union recv_frame *precv_frame)
4252 {
4253         return _SUCCESS;
4254 }
4255
4256 unsigned int OnAction_p2p(struct adapter *padapter, union recv_frame *precv_frame)
4257 {
4258 #ifdef CONFIG_88EU_P2P
4259         u8 *frame_body;
4260         u8 category, OUI_Subtype;
4261         u8 *pframe = precv_frame->u.hdr.rx_data;
4262         uint len = precv_frame->u.hdr.len;
4263         struct  wifidirect_info *pwdinfo = &(padapter->wdinfo);
4264
4265
4266         DBG_88E("%s\n", __func__);
4267
4268         /* check RA matches or not */
4269         if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
4270                 return _SUCCESS;
4271
4272         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
4273
4274         category = frame_body[0];
4275         if (category != RTW_WLAN_CATEGORY_P2P)
4276                 return _SUCCESS;
4277
4278         if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI)
4279                 return _SUCCESS;
4280
4281         len -= sizeof(struct rtw_ieee80211_hdr_3addr);
4282         OUI_Subtype = frame_body[5];
4283
4284         switch (OUI_Subtype) {
4285         case P2P_NOTICE_OF_ABSENCE:
4286                 break;
4287         case P2P_PRESENCE_REQUEST:
4288                 process_p2p_presence_req(pwdinfo, pframe, len);
4289                 break;
4290         case P2P_PRESENCE_RESPONSE:
4291                 break;
4292         case P2P_GO_DISC_REQUEST:
4293                 break;
4294         default:
4295                 break;
4296         }
4297 #endif /* CONFIG_88EU_P2P */
4298         return _SUCCESS;
4299 }
4300
4301 unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
4302 {
4303         int i;
4304         unsigned char   category;
4305         struct action_handler *ptable;
4306         unsigned char   *frame_body;
4307         u8 *pframe = precv_frame->u.hdr.rx_data;
4308
4309         frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
4310
4311         category = frame_body[0];
4312
4313         for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) {
4314                 ptable = &OnAction_tbl[i];
4315                 if (category == ptable->num)
4316                         ptable->func(padapter, precv_frame);
4317         }
4318         return _SUCCESS;
4319 }
4320
4321 unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
4322 {
4323         return _SUCCESS;
4324 }
4325
4326 struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
4327 {
4328         struct xmit_frame                       *pmgntframe;
4329         struct xmit_buf                         *pxmitbuf;
4330
4331         pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
4332         if (pmgntframe == NULL) {
4333                 DBG_88E("%s, alloc xmitframe fail\n", __func__);
4334                 return NULL;
4335         }
4336
4337         pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
4338         if (pxmitbuf == NULL) {
4339                 DBG_88E("%s, alloc xmitbuf fail\n", __func__);
4340                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
4341                 return NULL;
4342         }
4343         pmgntframe->frame_tag = MGNT_FRAMETAG;
4344         pmgntframe->pxmitbuf = pxmitbuf;
4345         pmgntframe->buf_addr = pxmitbuf->pbuf;
4346         pxmitbuf->priv_data = pmgntframe;
4347         return pmgntframe;
4348 }
4349
4350 /****************************************************************************
4351
4352 Following are some TX fuctions for WiFi MLME
4353
4354 *****************************************************************************/
4355
4356 void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
4357 {
4358         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4359
4360         pmlmeext->tx_rate = rate;
4361         DBG_88E("%s(): rate = %x\n", __func__, rate);
4362 }
4363
4364 void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
4365 {
4366         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4367
4368         _rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
4369
4370         pattrib->hdrlen = 24;
4371         pattrib->nr_frags = 1;
4372         pattrib->priority = 7;
4373         pattrib->mac_id = 0;
4374         pattrib->qsel = 0x12;
4375
4376         pattrib->pktlen = 0;
4377
4378         if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
4379                 pattrib->raid = 6;/* b mode */
4380         else
4381                 pattrib->raid = 5;/* a/g mode */
4382
4383         pattrib->encrypt = _NO_PRIVACY_;
4384         pattrib->bswenc = false;
4385
4386         pattrib->qos_en = false;
4387         pattrib->ht_en = false;
4388         pattrib->bwmode = HT_CHANNEL_WIDTH_20;
4389         pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4390         pattrib->sgi = false;
4391
4392         pattrib->seqnum = pmlmeext->mgnt_seq;
4393
4394         pattrib->retry_ctrl = true;
4395 }
4396
4397 void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
4398 {
4399         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4400                 return;
4401
4402         rtw_hal_mgnt_xmit(padapter, pmgntframe);
4403 }
4404
4405 s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
4406 {
4407         s32 ret = _FAIL;
4408         struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
4409         struct submit_ctx sctx;
4410
4411         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4412                 return ret;
4413
4414         rtw_sctx_init(&sctx, timeout_ms);
4415         pxmitbuf->sctx = &sctx;
4416
4417         ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
4418
4419         if (ret == _SUCCESS)
4420                 ret = rtw_sctx_wait(&sctx);
4421
4422          return ret;
4423 }
4424
4425 s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
4426 {
4427         s32 ret = _FAIL;
4428         u32 timeout_ms = 500;/*   500ms */
4429         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
4430
4431         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4432                 return -1;
4433
4434         _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
4435         pxmitpriv->ack_tx = true;
4436
4437         pmgntframe->ack_report = 1;
4438         if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
4439                 ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
4440         }
4441
4442         pxmitpriv->ack_tx = false;
4443         _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
4444
4445          return ret;
4446 }
4447
4448 static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
4449 {
4450         u8 *ssid_ie;
4451         int ssid_len_ori;
4452         int len_diff = 0;
4453
4454         ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
4455
4456         if (ssid_ie && ssid_len_ori > 0) {
4457                 switch (hidden_ssid_mode) {
4458                 case 1: {
4459                         u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
4460                         u32 remain_len = 0;
4461
4462                         remain_len = ies_len - (next_ie - ies);
4463
4464                         ssid_ie[1] = 0;
4465                         memcpy(ssid_ie+2, next_ie, remain_len);
4466                         len_diff -= ssid_len_ori;
4467
4468                         break;
4469                 }
4470                 case 2:
4471                         _rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
4472                         break;
4473                 default:
4474                         break;
4475                 }
4476         }
4477
4478         return len_diff;
4479 }
4480
4481 void issue_beacon(struct adapter *padapter, int timeout_ms)
4482 {
4483         struct xmit_frame       *pmgntframe;
4484         struct pkt_attrib       *pattrib;
4485         unsigned char   *pframe;
4486         struct rtw_ieee80211_hdr *pwlanhdr;
4487         __le16 *fctrl;
4488         unsigned int    rate_len;
4489         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4490 #if defined(CONFIG_88EU_AP_MODE)
4491         unsigned long irqL;
4492 #endif /* if defined (CONFIG_88EU_AP_MODE) */
4493         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4494         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4495         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4496         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
4497         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4498 #ifdef CONFIG_88EU_P2P
4499         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4500 #endif /* CONFIG_88EU_P2P */
4501
4502         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4503         if (pmgntframe == NULL) {
4504                 DBG_88E("%s, alloc mgnt frame fail\n", __func__);
4505                 return;
4506         }
4507 #if defined (CONFIG_88EU_AP_MODE)
4508         _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
4509 #endif /* if defined (CONFIG_88EU_AP_MODE) */
4510
4511         /* update attribute */
4512         pattrib = &pmgntframe->attrib;
4513         update_mgntframe_attrib(padapter, pattrib);
4514         pattrib->qsel = 0x10;
4515
4516         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4517
4518         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4519         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4520
4521
4522         fctrl = &(pwlanhdr->frame_ctl);
4523         *(fctrl) = 0;
4524
4525         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
4526         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4527         memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
4528
4529         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
4530         /* pmlmeext->mgnt_seq++; */
4531         SetFrameSubType(pframe, WIFI_BEACON);
4532
4533         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4534         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
4535
4536         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
4537 #ifdef CONFIG_88EU_P2P
4538                 /*  for P2P : Primary Device Type & Device Name */
4539                 u32 wpsielen = 0, insert_len = 0;
4540                 u8 *wpsie = NULL;
4541                 wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
4542
4543                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
4544                         uint wps_offset, remainder_ielen;
4545                         u8 *premainder_ie, *pframe_wscie;
4546
4547                         wps_offset = (uint)(wpsie - cur_network->IEs);
4548                         premainder_ie = wpsie + wpsielen;
4549                         remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
4550                         pframe_wscie = pframe + wps_offset;
4551                         memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);
4552                         pframe += (wps_offset + wpsielen);
4553                         pattrib->pktlen += (wps_offset + wpsielen);
4554
4555                         /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
4556                         /*      Primary Device Type */
4557                         /*      Type: */
4558                         *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
4559                         insert_len += 2;
4560
4561                         /*      Length: */
4562                         *(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
4563                         insert_len += 2;
4564
4565                         /*      Value: */
4566                         /*      Category ID */
4567                         *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
4568                         insert_len += 2;
4569
4570                         /*      OUI */
4571                         *(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
4572                         insert_len += 4;
4573
4574                         /*      Sub Category ID */
4575                         *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
4576                         insert_len += 2;
4577
4578                         /*      Device Name */
4579                         /*      Type: */
4580                         *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4581                         insert_len += 2;
4582
4583                         /*      Length: */
4584                         *(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
4585                         insert_len += 2;
4586
4587                         /*      Value: */
4588                         memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
4589                         insert_len += pwdinfo->device_name_len;
4590
4591                         /* update wsc ie length */
4592                         *(pframe_wscie+1) = (wpsielen-2) + insert_len;
4593
4594                         /* pframe move to end */
4595                         pframe += insert_len;
4596                         pattrib->pktlen += insert_len;
4597
4598                         /* copy remainder_ie to pframe */
4599                         memcpy(pframe, premainder_ie, remainder_ielen);
4600                         pframe += remainder_ielen;
4601                         pattrib->pktlen += remainder_ielen;
4602                 } else
4603 #endif /* CONFIG_88EU_P2P */
4604                 {
4605                         int len_diff;
4606                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
4607                         len_diff = update_hidden_ssid(
4608                                 pframe+_BEACON_IE_OFFSET_
4609                                 , cur_network->IELength-_BEACON_IE_OFFSET_
4610                                 , pmlmeinfo->hidden_ssid_mode
4611                         );
4612                         pframe += (cur_network->IELength+len_diff);
4613                         pattrib->pktlen += (cur_network->IELength+len_diff);
4614                 }
4615
4616                 {
4617                         u8 *wps_ie;
4618                         uint wps_ielen;
4619                         u8 sr = 0;
4620                         wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
4621                                 pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
4622                         if (wps_ie && wps_ielen > 0)
4623                                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
4624                         if (sr != 0)
4625                                 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
4626                         else
4627                                 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
4628                 }
4629
4630 #ifdef CONFIG_88EU_P2P
4631                 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
4632                         u32 len;
4633                         len = build_beacon_p2p_ie(pwdinfo, pframe);
4634
4635                         pframe += len;
4636                         pattrib->pktlen += len;
4637                 }
4638 #endif /* CONFIG_88EU_P2P */
4639
4640                 goto _issue_bcn;
4641         }
4642
4643         /* below for ad-hoc mode */
4644
4645         /* timestamp will be inserted by hardware */
4646         pframe += 8;
4647         pattrib->pktlen += 8;
4648
4649         /*  beacon interval: 2 bytes */
4650
4651         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4652
4653         pframe += 2;
4654         pattrib->pktlen += 2;
4655
4656         /*  capability info: 2 bytes */
4657
4658         memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4659
4660         pframe += 2;
4661         pattrib->pktlen += 2;
4662
4663         /*  SSID */
4664         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4665
4666         /*  supported rates... */
4667         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4668         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4669
4670         /*  DS parameter set */
4671         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
4672
4673         {
4674                 u8 erpinfo = 0;
4675                 u32 ATIMWindow;
4676                 /*  IBSS Parameter Set... */
4677                 ATIMWindow = 0;
4678                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4679
4680                 /* ERP IE */
4681                 pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4682         }
4683
4684         /*  EXTERNDED SUPPORTED RATE */
4685         if (rate_len > 8)
4686                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4687         /* todo:HT for adhoc */
4688 _issue_bcn:
4689
4690 #if defined (CONFIG_88EU_AP_MODE)
4691         pmlmepriv->update_bcn = false;
4692
4693         _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
4694 #endif /* if defined (CONFIG_88EU_AP_MODE) */
4695
4696         if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
4697                 DBG_88E("beacon frame too large\n");
4698                 return;
4699         }
4700
4701         pattrib->last_txcmdsz = pattrib->pktlen;
4702
4703         /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
4704         if (timeout_ms > 0)
4705                 dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
4706         else
4707                 dump_mgntframe(padapter, pmgntframe);
4708 }
4709
4710 void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
4711 {
4712         struct xmit_frame                       *pmgntframe;
4713         struct pkt_attrib                       *pattrib;
4714         unsigned char                                   *pframe;
4715         struct rtw_ieee80211_hdr        *pwlanhdr;
4716         __le16 *fctrl;
4717         unsigned char                                   *mac, *bssid;
4718         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4719 #if defined (CONFIG_88EU_AP_MODE)
4720         u8 *pwps_ie;
4721         uint wps_ielen;
4722         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4723 #endif /* if defined (CONFIG_88EU_AP_MODE) */
4724         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4725         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4726         struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
4727         unsigned int    rate_len;
4728 #ifdef CONFIG_88EU_P2P
4729         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4730 #endif /* CONFIG_88EU_P2P */
4731
4732         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4733         if (pmgntframe == NULL) {
4734                 DBG_88E("%s, alloc mgnt frame fail\n", __func__);
4735                 return;
4736         }
4737
4738         /* update attribute */
4739         pattrib = &pmgntframe->attrib;
4740         update_mgntframe_attrib(padapter, pattrib);
4741
4742         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4743
4744         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4745         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4746
4747         mac = myid(&(padapter->eeprompriv));
4748         bssid = cur_network->MacAddress;
4749
4750         fctrl = &(pwlanhdr->frame_ctl);
4751         *(fctrl) = 0;
4752         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4753         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4754         memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
4755
4756         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4757         pmlmeext->mgnt_seq++;
4758         SetFrameSubType(fctrl, WIFI_PROBERSP);
4759
4760         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4761         pattrib->pktlen = pattrib->hdrlen;
4762         pframe += pattrib->hdrlen;
4763
4764         if (cur_network->IELength > MAX_IE_SZ)
4765                 return;
4766
4767 #if defined(CONFIG_88EU_AP_MODE)
4768         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
4769                 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
4770
4771                 /* inerset & update wps_probe_resp_ie */
4772                 if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
4773                         uint wps_offset, remainder_ielen;
4774                         u8 *premainder_ie;
4775
4776                         wps_offset = (uint)(pwps_ie - cur_network->IEs);
4777
4778                         premainder_ie = pwps_ie + wps_ielen;
4779
4780                         remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
4781
4782                         memcpy(pframe, cur_network->IEs, wps_offset);
4783                         pframe += wps_offset;
4784                         pattrib->pktlen += wps_offset;
4785
4786                         wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
4787                         if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
4788                                 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
4789                                 pframe += wps_ielen+2;
4790                                 pattrib->pktlen += wps_ielen+2;
4791                         }
4792
4793                         if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
4794                                 memcpy(pframe, premainder_ie, remainder_ielen);
4795                                 pframe += remainder_ielen;
4796                                 pattrib->pktlen += remainder_ielen;
4797                         }
4798                 } else {
4799                         memcpy(pframe, cur_network->IEs, cur_network->IELength);
4800                         pframe += cur_network->IELength;
4801                         pattrib->pktlen += cur_network->IELength;
4802                 }
4803         } else
4804 #endif
4805         {
4806                 /* timestamp will be inserted by hardware */
4807                 pframe += 8;
4808                 pattrib->pktlen += 8;
4809
4810                 /*  beacon interval: 2 bytes */
4811
4812                 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4813
4814                 pframe += 2;
4815                 pattrib->pktlen += 2;
4816
4817                 /*  capability info: 2 bytes */
4818
4819                 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4820
4821                 pframe += 2;
4822                 pattrib->pktlen += 2;
4823
4824                 /* below for ad-hoc mode */
4825
4826                 /*  SSID */
4827                 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4828
4829                 /*  supported rates... */
4830                 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4831                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4832
4833                 /*  DS parameter set */
4834                 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
4835
4836                 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4837                         u8 erpinfo = 0;
4838                         u32 ATIMWindow;
4839                         /*  IBSS Parameter Set... */
4840                         /* ATIMWindow = cur->Configuration.ATIMWindow; */
4841                         ATIMWindow = 0;
4842                         pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4843
4844                         /* ERP IE */
4845                         pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4846                 }
4847
4848
4849                 /*  EXTERNDED SUPPORTED RATE */
4850                 if (rate_len > 8)
4851                         pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4852                 /* todo:HT for adhoc */
4853         }
4854
4855 #ifdef CONFIG_88EU_P2P
4856         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
4857                 u32 len;
4858                 len = build_probe_resp_p2p_ie(pwdinfo, pframe);
4859
4860                 pframe += len;
4861                 pattrib->pktlen += len;
4862         }
4863 #endif /* CONFIG_88EU_P2P */
4864
4865         pattrib->last_txcmdsz = pattrib->pktlen;
4866
4867         dump_mgntframe(padapter, pmgntframe);
4868
4869         return;
4870 }
4871
4872 static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
4873 {
4874         int ret = _FAIL;
4875         struct xmit_frame               *pmgntframe;
4876         struct pkt_attrib               *pattrib;
4877         unsigned char                   *pframe;
4878         struct rtw_ieee80211_hdr        *pwlanhdr;
4879         __le16 *fctrl;
4880         unsigned char                   *mac;
4881         unsigned char                   bssrate[NumRates];
4882         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4883         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4884         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4885         int     bssrate_len = 0;
4886         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4887
4888         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
4889
4890         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4891         if (pmgntframe == NULL)
4892                 goto exit;
4893
4894         /* update attribute */
4895         pattrib = &pmgntframe->attrib;
4896         update_mgntframe_attrib(padapter, pattrib);
4897
4898
4899         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4900
4901         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4902         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4903
4904         mac = myid(&(padapter->eeprompriv));
4905
4906         fctrl = &(pwlanhdr->frame_ctl);
4907         *(fctrl) = 0;
4908
4909         if (da) {
4910                 /*      unicast probe request frame */
4911                 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4912                 memcpy(pwlanhdr->addr3, da, ETH_ALEN);
4913         } else {
4914                 /*      broadcast probe request frame */
4915                 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
4916                 memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
4917         }
4918
4919         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4920
4921         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4922         pmlmeext->mgnt_seq++;
4923         SetFrameSubType(pframe, WIFI_PROBEREQ);
4924
4925         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
4926         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
4927
4928         if (pssid)
4929                 pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
4930         else
4931                 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
4932
4933         get_rate_set(padapter, bssrate, &bssrate_len);
4934
4935         if (bssrate_len > 8) {
4936                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
4937                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
4938         } else {
4939                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
4940         }
4941
4942         /* add wps_ie for wps2.0 */
4943         if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
4944                 memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
4945                 pframe += pmlmepriv->wps_probe_req_ie_len;
4946                 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4947         }
4948
4949         pattrib->last_txcmdsz = pattrib->pktlen;
4950
4951         RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4952                  ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
4953
4954         if (wait_ack) {
4955                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
4956         } else {
4957                 dump_mgntframe(padapter, pmgntframe);
4958                 ret = _SUCCESS;
4959         }
4960
4961 exit:
4962         return ret;
4963 }
4964
4965 inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
4966 {
4967         _issue_probereq(padapter, pssid, da, false);
4968 }
4969
4970 int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da,
4971         int try_cnt, int wait_ms)
4972 {
4973         int ret;
4974         int i = 0;
4975         u32 start = rtw_get_current_time();
4976
4977         do {
4978                 ret = _issue_probereq(padapter, pssid, da, wait_ms > 0 ? true : false);
4979
4980                 i++;
4981
4982                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
4983                         break;
4984
4985                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
4986                         rtw_msleep_os(wait_ms);
4987
4988         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
4989
4990         if (ret != _FAIL) {
4991                 ret = _SUCCESS;
4992                 goto exit;
4993         }
4994
4995         if (try_cnt && wait_ms) {
4996                 if (da)
4997                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
4998                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
4999                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5000                 else
5001                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5002                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5003                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5004         }
5005 exit:
5006         return ret;
5007 }
5008
5009 /*  if psta == NULL, indiate we are station(client) now... */
5010 void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
5011 {
5012         struct xmit_frame *pmgntframe;
5013         struct pkt_attrib *pattrib;
5014         unsigned char *pframe;
5015         struct rtw_ieee80211_hdr *pwlanhdr;
5016         __le16 *fctrl;
5017         unsigned int val32;
5018         u16 val16;
5019 #ifdef CONFIG_88EU_AP_MODE
5020         __le16 le_val16;
5021 #endif
5022         int use_shared_key = 0;
5023         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
5024         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5025         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5026
5027         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5028         if (pmgntframe == NULL)
5029                 return;
5030
5031         /* update attribute */
5032         pattrib = &pmgntframe->attrib;
5033         update_mgntframe_attrib(padapter, pattrib);
5034
5035         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5036
5037         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5038         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5039
5040         fctrl = &(pwlanhdr->frame_ctl);
5041         *(fctrl) = 0;
5042
5043         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5044         pmlmeext->mgnt_seq++;
5045         SetFrameSubType(pframe, WIFI_AUTH);
5046
5047         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5048         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5049
5050
5051         if (psta) {/*  for AP mode */
5052 #ifdef CONFIG_88EU_AP_MODE
5053
5054                 memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
5055                 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5056                 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
5057
5058
5059                 /*  setting auth algo number */
5060                 val16 = (u16)psta->authalg;
5061
5062                 if (status != _STATS_SUCCESSFUL_)
5063                         val16 = 0;
5064
5065                 if (val16) {
5066                         le_val16 = cpu_to_le16(val16);
5067                         use_shared_key = 1;
5068                 } else {
5069                         le_val16 = 0;
5070                 }
5071
5072                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &(pattrib->pktlen));
5073
5074                 /*  setting auth seq number */
5075                 val16 = (u16)psta->auth_seq;
5076                 le_val16 = cpu_to_le16(val16);
5077                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &(pattrib->pktlen));
5078
5079                 /*  setting status code... */
5080                 val16 = status;
5081                 le_val16 = cpu_to_le16(val16);
5082                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &(pattrib->pktlen));
5083
5084                 /*  added challenging text... */
5085                 if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
5086                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
5087 #endif
5088         } else {
5089                 __le32 le_tmp32;
5090                 __le16 le_tmp16;
5091                 memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5092                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5093                 memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5094
5095                 /*  setting auth algo number */
5096                 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
5097                 if (val16)
5098                         use_shared_key = 1;
5099
5100                 /* setting IV for auth seq #3 */
5101                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
5102                         val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
5103                         le_tmp32 = cpu_to_le32(val32);
5104                         pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
5105
5106                         pattrib->iv_len = 4;
5107                 }
5108
5109                 le_tmp16 = cpu_to_le16(val16);
5110                 pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
5111
5112                 /*  setting auth seq number */
5113                 val16 = pmlmeinfo->auth_seq;
5114                 le_tmp16 = cpu_to_le16(val16);
5115                 pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
5116
5117
5118                 /*  setting status code... */
5119                 le_tmp16 = cpu_to_le16(status);
5120                 pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
5121
5122                 /*  then checking to see if sending challenging text... */
5123                 if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
5124                         pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
5125
5126                         SetPrivacy(fctrl);
5127
5128                         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5129
5130                         pattrib->encrypt = _WEP40_;
5131
5132                         pattrib->icv_len = 4;
5133
5134                         pattrib->pktlen += pattrib->icv_len;
5135                 }
5136         }
5137
5138         pattrib->last_txcmdsz = pattrib->pktlen;
5139
5140         rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
5141         DBG_88E("%s\n", __func__);
5142         dump_mgntframe(padapter, pmgntframe);
5143
5144         return;
5145 }
5146
5147
5148 void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
5149 {
5150 #ifdef CONFIG_88EU_AP_MODE
5151         struct xmit_frame       *pmgntframe;
5152         struct rtw_ieee80211_hdr        *pwlanhdr;
5153         struct pkt_attrib *pattrib;
5154         unsigned char   *pbuf, *pframe;
5155         unsigned short val;
5156         __le16 *fctrl;
5157         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
5158         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5159         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5160         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5161         struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
5162         u8 *ie = pnetwork->IEs;
5163         __le16 lestatus, leval;
5164 #ifdef CONFIG_88EU_P2P
5165         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5166 #endif /* CONFIG_88EU_P2P */
5167
5168         DBG_88E("%s\n", __func__);
5169
5170         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5171         if (pmgntframe == NULL)
5172                 return;
5173
5174         /* update attribute */
5175         pattrib = &pmgntframe->attrib;
5176         update_mgntframe_attrib(padapter, pattrib);
5177
5178
5179         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5180
5181         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5182         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5183
5184         fctrl = &(pwlanhdr->frame_ctl);
5185         *(fctrl) = 0;
5186
5187         memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
5188         memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
5189         memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5190
5191
5192         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5193         pmlmeext->mgnt_seq++;
5194         if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
5195                 SetFrameSubType(pwlanhdr, pkt_type);
5196         else
5197                 return;
5198
5199         pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5200         pattrib->pktlen += pattrib->hdrlen;
5201         pframe += pattrib->hdrlen;
5202
5203         /* capability */
5204         val = *(unsigned short *)rtw_get_capability_from_ie(ie);
5205
5206         pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
5207
5208         lestatus = cpu_to_le16(status);
5209         pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&lestatus, &(pattrib->pktlen));
5210
5211         leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
5212         pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&leval, &(pattrib->pktlen));
5213
5214         if (pstat->bssratelen <= 8) {
5215                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
5216         } else {
5217                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
5218                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
5219         }
5220
5221         if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
5222                 uint ie_len = 0;
5223
5224                 /* FILL HT CAP INFO IE */
5225                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
5226                 if (pbuf && ie_len > 0) {
5227                         memcpy(pframe, pbuf, ie_len+2);
5228                         pframe += (ie_len+2);
5229                         pattrib->pktlen += (ie_len+2);
5230                 }
5231
5232                 /* FILL HT ADD INFO IE */
5233                 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
5234                 if (pbuf && ie_len > 0) {
5235                         memcpy(pframe, pbuf, ie_len+2);
5236                         pframe += (ie_len+2);
5237                         pattrib->pktlen += (ie_len+2);
5238                 }
5239         }
5240
5241         /* FILL WMM IE */
5242         if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
5243                 uint ie_len = 0;
5244                 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
5245
5246                 for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
5247                         pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
5248                         if (pbuf && _rtw_memcmp(pbuf+2, WMM_PARA_IE, 6)) {
5249                                 memcpy(pframe, pbuf, ie_len+2);
5250                                 pframe += (ie_len+2);
5251                                 pattrib->pktlen += (ie_len+2);
5252                                 break;
5253                         }
5254
5255                         if ((pbuf == NULL) || (ie_len == 0))
5256                                 break;
5257                 }
5258         }
5259
5260         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
5261                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
5262
5263         /* add WPS IE ie for wps 2.0 */
5264         if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
5265                 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
5266
5267                 pframe += pmlmepriv->wps_assoc_resp_ie_len;
5268                 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
5269         }
5270
5271 #ifdef CONFIG_88EU_P2P
5272         if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) {
5273                 u32 len;
5274
5275                 len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
5276
5277                 pframe += len;
5278                 pattrib->pktlen += len;
5279         }
5280 #endif /* CONFIG_88EU_P2P */
5281         pattrib->last_txcmdsz = pattrib->pktlen;
5282         dump_mgntframe(padapter, pmgntframe);
5283 #endif
5284 }
5285
5286 void issue_assocreq(struct adapter *padapter)
5287 {
5288         int ret = _FAIL;
5289         struct xmit_frame       *pmgntframe;
5290         struct pkt_attrib       *pattrib;
5291         unsigned char           *pframe, *p;
5292         struct rtw_ieee80211_hdr        *pwlanhdr;
5293         __le16 *fctrl;
5294         __le16          le_tmp;
5295         unsigned int    i, j, ie_len, index = 0;
5296         unsigned char   rf_type, bssrate[NumRates], sta_bssrate[NumRates];
5297         struct ndis_802_11_var_ie *pIE;
5298         struct registry_priv    *pregpriv = &padapter->registrypriv;
5299         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
5300         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5301         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5302         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5303         int     bssrate_len = 0, sta_bssrate_len = 0;
5304 #ifdef CONFIG_88EU_P2P
5305         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5306         u8 p2pie[255] = { 0x00 };
5307         u16 p2pielen = 0;
5308 #endif /* CONFIG_88EU_P2P */
5309
5310         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5311         if (pmgntframe == NULL)
5312                 goto exit;
5313
5314         /* update attribute */
5315         pattrib = &pmgntframe->attrib;
5316         update_mgntframe_attrib(padapter, pattrib);
5317
5318         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5319         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5320         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5321
5322         fctrl = &(pwlanhdr->frame_ctl);
5323         *(fctrl) = 0;
5324         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5325         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5326         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5327
5328         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5329         pmlmeext->mgnt_seq++;
5330         SetFrameSubType(pframe, WIFI_ASSOCREQ);
5331
5332         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5333         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5334
5335         /* caps */
5336
5337         memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
5338
5339         pframe += 2;
5340         pattrib->pktlen += 2;
5341
5342         /* listen interval */
5343         /* todo: listen interval for power saving */
5344         le_tmp = cpu_to_le16(3);
5345         memcpy(pframe , (unsigned char *)&le_tmp, 2);
5346         pframe += 2;
5347         pattrib->pktlen += 2;
5348
5349         /* SSID */
5350         pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
5351
5352         /* supported rate & extended supported rate */
5353
5354         /*  Check if the AP's supported rates are also supported by STA. */
5355         get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
5356
5357         if (pmlmeext->cur_channel == 14)/*  for JAPAN, channel 14 can only uses B Mode(CCK) */
5358                 sta_bssrate_len = 4;
5359
5360         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
5361                 if (pmlmeinfo->network.SupportedRates[i] == 0)
5362                         break;
5363                 DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
5364         }
5365
5366         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
5367                 if (pmlmeinfo->network.SupportedRates[i] == 0)
5368                         break;
5369
5370                 /*  Check if the AP's supported rates are also supported by STA. */
5371                 for (j = 0; j < sta_bssrate_len; j++) {
5372                          /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
5373                         if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
5374                                         == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
5375                                 break;
5376                 }
5377
5378                 if (j == sta_bssrate_len) {
5379                         /*  the rate is not supported by STA */
5380                         DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
5381                 } else {
5382                         /*  the rate is supported by STA */
5383                         bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
5384                 }
5385         }
5386
5387         bssrate_len = index;
5388         DBG_88E("bssrate_len=%d\n", bssrate_len);
5389
5390         if (bssrate_len == 0) {
5391                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
5392                 rtw_free_xmitframe(pxmitpriv, pmgntframe);
5393                 goto exit; /* don't connect to AP if no joint supported rate */
5394         }
5395
5396
5397         if (bssrate_len > 8) {
5398                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
5399                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
5400         } else {
5401                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
5402         }
5403
5404         /* RSN */
5405         p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
5406         if (p != NULL)
5407                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, (p + 2), &(pattrib->pktlen));
5408
5409         /* HT caps */
5410         if (padapter->mlmepriv.htpriv.ht_option) {
5411                 p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
5412                 if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) {
5413                         memcpy(&(pmlmeinfo->HT_caps), (p + 2), sizeof(struct HT_caps_element));
5414
5415                         /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
5416                         if (pregpriv->cbw40_enable == 0)
5417                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
5418                         else
5419                                 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1));
5420
5421                         /* todo: disable SM power save mode */
5422                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c);
5423
5424                         rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
5425                         switch (rf_type) {
5426                         case RF_1T1R:
5427                                 if (pregpriv->rx_stbc)
5428                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
5429                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
5430                                 break;
5431                         case RF_2T2R:
5432                         case RF_1T2R:
5433                         default:
5434                                 if ((pregpriv->rx_stbc == 0x3) ||/* enable for 2.4/5 GHz */
5435                                     ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */
5436                                     (pregpriv->wifi_spec == 1)) {
5437                                         DBG_88E("declare supporting RX STBC\n");
5438                                         pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
5439                                 }
5440                                 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16);
5441                                 break;
5442                         }
5443                         pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
5444                 }
5445         }
5446
5447         /* vendor specific IE, such as WPA, WMM, WPS */
5448         for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
5449                 pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
5450
5451                 switch (pIE->ElementID) {
5452                 case _VENDOR_SPECIFIC_IE_:
5453                         if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
5454                             (_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
5455                             (_rtw_memcmp(pIE->data, WPS_OUI, 4))) {
5456                                 if (!padapter->registrypriv.wifi_spec) {
5457                                         /* Commented by Kurt 20110629 */
5458                                         /* In some older APs, WPS handshake */
5459                                         /* would be fail if we append vender extensions informations to AP */
5460                                         if (_rtw_memcmp(pIE->data, WPS_OUI, 4))
5461                                                 pIE->Length = 14;
5462                                 }
5463                                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &(pattrib->pktlen));
5464                         }
5465                         break;
5466                 default:
5467                         break;
5468                 }
5469                 i += (pIE->Length + 2);
5470         }
5471
5472         if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
5473                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
5474
5475 #ifdef CONFIG_88EU_P2P
5476
5477         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
5478                 /*      Should add the P2P IE in the association request frame. */
5479                 /*      P2P OUI */
5480
5481                 p2pielen = 0;
5482                 p2pie[p2pielen++] = 0x50;
5483                 p2pie[p2pielen++] = 0x6F;
5484                 p2pie[p2pielen++] = 0x9A;
5485                 p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
5486
5487                 /*      Commented by Albert 20101109 */
5488                 /*      According to the P2P Specification, the association request frame should contain 3 P2P attributes */
5489                 /*      1. P2P Capability */
5490                 /*      2. Extended Listen Timing */
5491                 /*      3. Device Info */
5492                 /*      Commented by Albert 20110516 */
5493                 /*      4. P2P Interface */
5494
5495                 /*      P2P Capability */
5496                 /*      Type: */
5497                 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
5498
5499                 /*      Length: */
5500                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
5501                 p2pielen += 2;
5502
5503                 /*      Value: */
5504                 /*      Device Capability Bitmap, 1 byte */
5505                 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
5506
5507                 /*      Group Capability Bitmap, 1 byte */
5508                 if (pwdinfo->persistent_supported)
5509                         p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
5510                 else
5511                         p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
5512
5513                 /*      Extended Listen Timing */
5514                 /*      Type: */
5515                 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
5516
5517                 /*      Length: */
5518                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
5519                 p2pielen += 2;
5520
5521                 /*      Value: */
5522                 /*      Availability Period */
5523                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5524                 p2pielen += 2;
5525
5526                 /*      Availability Interval */
5527                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5528                 p2pielen += 2;
5529
5530                 /*      Device Info */
5531                 /*      Type: */
5532                 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
5533
5534                 /*      Length: */
5535                 /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
5536                 /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
5537                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
5538                 p2pielen += 2;
5539
5540                 /*      Value: */
5541                 /*      P2P Device Address */
5542                 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
5543                 p2pielen += ETH_ALEN;
5544
5545                 /*      Config Method */
5546                 /*      This field should be big endian. Noted by P2P specification. */
5547                 if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
5548                     (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
5549                         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
5550                 else
5551                         *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
5552
5553                 p2pielen += 2;
5554
5555                 /*      Primary Device Type */
5556                 /*      Category ID */
5557                 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
5558                 p2pielen += 2;
5559
5560                 /*      OUI */
5561                 *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
5562                 p2pielen += 4;
5563
5564                 /*      Sub Category ID */
5565                 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
5566                 p2pielen += 2;
5567
5568                 /*      Number of Secondary Device Types */
5569                 p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
5570
5571                 /*      Device Name */
5572                 /*      Type: */
5573                 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
5574                 p2pielen += 2;
5575
5576                 /*      Length: */
5577                 *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
5578                 p2pielen += 2;
5579
5580                 /*      Value: */
5581                 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
5582                 p2pielen += pwdinfo->device_name_len;
5583
5584                 /*      P2P Interface */
5585                 /*      Type: */
5586                 p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
5587
5588                 /*      Length: */
5589                 *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
5590                 p2pielen += 2;
5591
5592                 /*      Value: */
5593                 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);       /*      P2P Device Address */
5594                 p2pielen += ETH_ALEN;
5595
5596                 p2pie[p2pielen++] = 1;  /*      P2P Interface Address Count */
5597
5598                 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);       /*      P2P Interface Address List */
5599                 p2pielen += ETH_ALEN;
5600
5601                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
5602         }
5603
5604 #endif /* CONFIG_88EU_P2P */
5605
5606         pattrib->last_txcmdsz = pattrib->pktlen;
5607         dump_mgntframe(padapter, pmgntframe);
5608
5609         ret = _SUCCESS;
5610
5611 exit:
5612         if (ret == _SUCCESS)
5613                 rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
5614         else
5615                 rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
5616
5617         return;
5618 }
5619
5620 /* when wait_ack is ture, this function shoule be called at process context */
5621 static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
5622 {
5623         int ret = _FAIL;
5624         struct xmit_frame                       *pmgntframe;
5625         struct pkt_attrib                       *pattrib;
5626         unsigned char                                   *pframe;
5627         struct rtw_ieee80211_hdr        *pwlanhdr;
5628         __le16 *fctrl;
5629         struct xmit_priv        *pxmitpriv;
5630         struct mlme_ext_priv    *pmlmeext;
5631         struct mlme_ext_info    *pmlmeinfo;
5632
5633         if (!padapter)
5634                 goto exit;
5635
5636         pxmitpriv = &(padapter->xmitpriv);
5637         pmlmeext = &(padapter->mlmeextpriv);
5638         pmlmeinfo = &(pmlmeext->mlmext_info);
5639
5640         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5641         if (pmgntframe == NULL)
5642                 goto exit;
5643
5644         /* update attribute */
5645         pattrib = &pmgntframe->attrib;
5646         update_mgntframe_attrib(padapter, pattrib);
5647         pattrib->retry_ctrl = false;
5648
5649         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5650
5651         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5652         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5653
5654         fctrl = &(pwlanhdr->frame_ctl);
5655         *(fctrl) = 0;
5656
5657         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
5658                 SetFrDs(fctrl);
5659         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
5660                 SetToDs(fctrl);
5661
5662         if (power_mode)
5663                 SetPwrMgt(fctrl);
5664
5665         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5666         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5667         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5668
5669         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5670         pmlmeext->mgnt_seq++;
5671         SetFrameSubType(pframe, WIFI_DATA_NULL);
5672
5673         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5674         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5675
5676         pattrib->last_txcmdsz = pattrib->pktlen;
5677
5678         if (wait_ack) {
5679                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5680         } else {
5681                 dump_mgntframe(padapter, pmgntframe);
5682                 ret = _SUCCESS;
5683         }
5684
5685 exit:
5686         return ret;
5687 }
5688
5689
5690 /* when wait_ms > 0 , this function shoule be called at process context */
5691 /* da == NULL for station mode */
5692 int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
5693 {
5694         int ret;
5695         int i = 0;
5696         u32 start = rtw_get_current_time();
5697         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5698         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5699
5700         /* da == NULL, assum it's null data for sta to ap*/
5701         if (da == NULL)
5702                 da = get_my_bssid(&(pmlmeinfo->network));
5703
5704         do {
5705                 ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? true : false);
5706
5707                 i++;
5708
5709                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5710                         break;
5711
5712                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5713                         rtw_msleep_os(wait_ms);
5714         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5715
5716         if (ret != _FAIL) {
5717                 ret = _SUCCESS;
5718                 goto exit;
5719         }
5720
5721         if (try_cnt && wait_ms) {
5722                 if (da)
5723                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
5724                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
5725                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5726                 else
5727                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5728                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5729                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5730         }
5731 exit:
5732         return ret;
5733 }
5734
5735 /* when wait_ack is ture, this function shoule be called at process context */
5736 static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
5737 {
5738         int ret = _FAIL;
5739         struct xmit_frame                       *pmgntframe;
5740         struct pkt_attrib                       *pattrib;
5741         unsigned char                                   *pframe;
5742         struct rtw_ieee80211_hdr        *pwlanhdr;
5743         __le16 *fctrl;
5744         unsigned short *qc;
5745         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
5746         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5747         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5748
5749         DBG_88E("%s\n", __func__);
5750
5751         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5752         if (pmgntframe == NULL)
5753                 goto exit;
5754
5755         /* update attribute */
5756         pattrib = &pmgntframe->attrib;
5757         update_mgntframe_attrib(padapter, pattrib);
5758
5759         pattrib->hdrlen += 2;
5760         pattrib->qos_en = true;
5761         pattrib->eosp = 1;
5762         pattrib->ack_policy = 0;
5763         pattrib->mdata = 0;
5764
5765         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5766
5767         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5768         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5769
5770         fctrl = &(pwlanhdr->frame_ctl);
5771         *(fctrl) = 0;
5772
5773         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
5774                 SetFrDs(fctrl);
5775         else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
5776                 SetToDs(fctrl);
5777
5778         if (pattrib->mdata)
5779                 SetMData(fctrl);
5780
5781         qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
5782
5783         SetPriority(qc, tid);
5784
5785         SetEOSP(qc, pattrib->eosp);
5786
5787         SetAckpolicy(qc, pattrib->ack_policy);
5788
5789         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5790         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5791         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5792
5793         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5794         pmlmeext->mgnt_seq++;
5795         SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
5796
5797         pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
5798         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
5799
5800         pattrib->last_txcmdsz = pattrib->pktlen;
5801
5802         if (wait_ack) {
5803                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5804         } else {
5805                 dump_mgntframe(padapter, pmgntframe);
5806                 ret = _SUCCESS;
5807         }
5808
5809 exit:
5810         return ret;
5811 }
5812
5813 /* when wait_ms > 0 , this function shoule be called at process context */
5814 /* da == NULL for station mode */
5815 int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
5816 {
5817         int ret;
5818         int i = 0;
5819         u32 start = rtw_get_current_time();
5820         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5821         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5822
5823         /* da == NULL, assum it's null data for sta to ap*/
5824         if (da == NULL)
5825                 da = get_my_bssid(&(pmlmeinfo->network));
5826
5827         do {
5828                 ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0 ? true : false);
5829
5830                 i++;
5831
5832                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5833                         break;
5834
5835                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5836                         rtw_msleep_os(wait_ms);
5837         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5838
5839         if (ret != _FAIL) {
5840                 ret = _SUCCESS;
5841                 goto exit;
5842         }
5843
5844         if (try_cnt && wait_ms) {
5845                 if (da)
5846                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
5847                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
5848                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5849                 else
5850                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5851                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5852                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5853         }
5854 exit:
5855         return ret;
5856 }
5857
5858 static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
5859 {
5860         struct xmit_frame                       *pmgntframe;
5861         struct pkt_attrib                       *pattrib;
5862         unsigned char                                   *pframe;
5863         struct rtw_ieee80211_hdr        *pwlanhdr;
5864         __le16 *fctrl;
5865         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
5866         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5867         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5868         int ret = _FAIL;
5869         __le16 le_tmp;
5870 #ifdef CONFIG_88EU_P2P
5871         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5872 #endif /* CONFIG_88EU_P2P */
5873
5874 #ifdef CONFIG_88EU_P2P
5875         if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
5876                 _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
5877                 _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
5878         }
5879 #endif /* CONFIG_88EU_P2P */
5880
5881         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5882         if (pmgntframe == NULL)
5883                 goto exit;
5884
5885         /* update attribute */
5886         pattrib = &pmgntframe->attrib;
5887         update_mgntframe_attrib(padapter, pattrib);
5888         pattrib->retry_ctrl = false;
5889
5890         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5891
5892         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5893         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5894
5895         fctrl = &(pwlanhdr->frame_ctl);
5896         *(fctrl) = 0;
5897
5898         memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5899         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5900         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5901
5902         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5903         pmlmeext->mgnt_seq++;
5904         SetFrameSubType(pframe, WIFI_DEAUTH);
5905
5906         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5907         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5908
5909         le_tmp = cpu_to_le16(reason);
5910         pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&le_tmp, &(pattrib->pktlen));
5911
5912         pattrib->last_txcmdsz = pattrib->pktlen;
5913
5914
5915         if (wait_ack) {
5916                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5917         } else {
5918                 dump_mgntframe(padapter, pmgntframe);
5919                 ret = _SUCCESS;
5920         }
5921
5922 exit:
5923         return ret;
5924 }
5925
5926 int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
5927 {
5928         DBG_88E("%s to %pM\n", __func__, da);
5929         return _issue_deauth(padapter, da, reason, false);
5930 }
5931
5932 int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
5933         int wait_ms)
5934 {
5935         int ret;
5936         int i = 0;
5937         u32 start = rtw_get_current_time();
5938
5939         do {
5940                 ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? true : false);
5941
5942                 i++;
5943
5944                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5945                         break;
5946
5947                 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5948                         rtw_msleep_os(wait_ms);
5949         } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5950
5951         if (ret != _FAIL) {
5952                 ret = _SUCCESS;
5953                 goto exit;
5954         }
5955
5956         if (try_cnt && wait_ms) {
5957                 if (da)
5958                         DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
5959                                 FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
5960                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5961                 else
5962                         DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5963                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5964                                 ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5965         }
5966 exit:
5967         return ret;
5968 }
5969
5970 void issue_action_spct_ch_switch (struct adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
5971 {
5972         struct xmit_frame                       *pmgntframe;
5973         struct pkt_attrib                       *pattrib;
5974         unsigned char                           *pframe;
5975         struct rtw_ieee80211_hdr        *pwlanhdr;
5976         __le16 *fctrl;
5977         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
5978         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5979
5980
5981         DBG_88E(FUNC_NDEV_FMT" ra =%pM, ch:%u, offset:%u\n",
5982                 FUNC_NDEV_ARG(padapter->pnetdev), ra, new_ch, ch_offset);
5983
5984         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5985         if (pmgntframe == NULL)
5986                 return;
5987
5988         /* update attribute */
5989         pattrib = &pmgntframe->attrib;
5990         update_mgntframe_attrib(padapter, pattrib);
5991
5992         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5993
5994         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5995         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5996
5997         fctrl = &(pwlanhdr->frame_ctl);
5998         *(fctrl) = 0;
5999
6000         memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
6001         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
6002         memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
6003
6004         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6005         pmlmeext->mgnt_seq++;
6006         SetFrameSubType(pframe, WIFI_ACTION);
6007
6008         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6009         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6010
6011         /* category, action */
6012         {
6013                 u8 category, action;
6014                 category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
6015                 action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
6016
6017                 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6018                 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
6019         }
6020
6021         pframe = rtw_set_ie_ch_switch (pframe, &(pattrib->pktlen), 0, new_ch, 0);
6022         pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
6023                 hal_ch_offset_to_secondary_ch_offset(ch_offset));
6024
6025         pattrib->last_txcmdsz = pattrib->pktlen;
6026
6027         dump_mgntframe(padapter, pmgntframe);
6028 }
6029
6030 void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
6031 {
6032         u8 category = RTW_WLAN_CATEGORY_BACK;
6033         u16 start_seq;
6034         u16 BA_para_set;
6035         u16 reason_code;
6036         u16 BA_timeout_value;
6037         __le16  le_tmp;
6038         u16 BA_starting_seqctrl = 0;
6039         enum ht_cap_ampdu_factor max_rx_ampdu_factor;
6040         struct xmit_frame *pmgntframe;
6041         struct pkt_attrib *pattrib;
6042         u8 *pframe;
6043         struct rtw_ieee80211_hdr *pwlanhdr;
6044         __le16 *fctrl;
6045         struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
6046         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
6047         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6048         struct sta_info *psta;
6049         struct sta_priv *pstapriv = &padapter->stapriv;
6050         struct registry_priv *pregpriv = &padapter->registrypriv;
6051
6052         DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
6053
6054         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
6055         if (pmgntframe == NULL)
6056                 return;
6057
6058         /* update attribute */
6059         pattrib = &pmgntframe->attrib;
6060         update_mgntframe_attrib(padapter, pattrib);
6061
6062         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6063
6064         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6065         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6066
6067         fctrl = &(pwlanhdr->frame_ctl);
6068         *(fctrl) = 0;
6069
6070         /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
6071         memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
6072         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6073         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6074
6075         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6076         pmlmeext->mgnt_seq++;
6077         SetFrameSubType(pframe, WIFI_ACTION);
6078
6079         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6080         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6081
6082         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6083         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
6084
6085         if (category == 3) {
6086                 switch (action) {
6087                 case 0: /* ADDBA req */
6088                         do {
6089                                 pmlmeinfo->dialogToken++;
6090                         } while (pmlmeinfo->dialogToken == 0);
6091                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
6092
6093                         BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
6094                         le_tmp = cpu_to_le16(BA_para_set);
6095                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6096
6097                         BA_timeout_value = 5000;/*  5ms */
6098                         le_tmp = cpu_to_le16(BA_timeout_value);
6099                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6100
6101                         psta = rtw_get_stainfo(pstapriv, raddr);
6102                         if (psta != NULL) {
6103                                 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
6104
6105                                 DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
6106
6107                                 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
6108
6109                                 BA_starting_seqctrl = start_seq << 4;
6110                         }
6111                         le_tmp = cpu_to_le16(BA_starting_seqctrl);
6112                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6113                         break;
6114                 case 1: /* ADDBA rsp */
6115                         pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
6116                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
6117                         rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
6118                         if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
6119                                 BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
6120                         else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
6121                                 BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
6122                         else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
6123                                 BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
6124                         else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
6125                                 BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
6126                         else
6127                                 BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
6128
6129                         if (pregpriv->ampdu_amsdu == 0)/* disabled */
6130                                 BA_para_set = BA_para_set & ~BIT(0);
6131                         else if (pregpriv->ampdu_amsdu == 1)/* enabled */
6132                                 BA_para_set = BA_para_set | BIT(0);
6133                         le_tmp = cpu_to_le16(BA_para_set);
6134
6135                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6136                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
6137                         break;
6138                 case 2:/* DELBA */
6139                         BA_para_set = (status & 0x1F) << 3;
6140                         le_tmp = cpu_to_le16(BA_para_set);
6141                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6142
6143                         reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
6144                         le_tmp = cpu_to_le16(reason_code);
6145                         pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6146                         break;
6147                 default:
6148                         break;
6149                 }
6150         }
6151
6152         pattrib->last_txcmdsz = pattrib->pktlen;
6153
6154         dump_mgntframe(padapter, pmgntframe);
6155 }
6156
6157 static void issue_action_BSSCoexistPacket(struct adapter *padapter)
6158 {
6159         unsigned long   irqL;
6160         struct list_head *plist, *phead;
6161         unsigned char category, action;
6162         struct xmit_frame                       *pmgntframe;
6163         struct pkt_attrib                       *pattrib;
6164         unsigned char                           *pframe;
6165         struct rtw_ieee80211_hdr        *pwlanhdr;
6166         __le16 *fctrl;
6167         struct  wlan_network    *pnetwork = NULL;
6168         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
6169         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6170         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6171         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6172         struct __queue *queue   = &(pmlmepriv->scanned_queue);
6173         u8 InfoContent[16] = {0};
6174         u8 ICS[8][15];
6175         if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
6176                 return;
6177
6178         if (pmlmeinfo->bwmode_updated)
6179                 return;
6180
6181
6182         DBG_88E("%s\n", __func__);
6183
6184
6185         category = RTW_WLAN_CATEGORY_PUBLIC;
6186         action = ACT_PUBLIC_BSSCOEXIST;
6187
6188         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
6189         if (pmgntframe == NULL)
6190                 return;
6191
6192         /* update attribute */
6193         pattrib = &pmgntframe->attrib;
6194         update_mgntframe_attrib(padapter, pattrib);
6195
6196         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6197
6198         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6199         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6200
6201         fctrl = &(pwlanhdr->frame_ctl);
6202         *(fctrl) = 0;
6203
6204         memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6205         memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6206         memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6207
6208         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6209         pmlmeext->mgnt_seq++;
6210         SetFrameSubType(pframe, WIFI_ACTION);
6211
6212         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6213         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6214
6215         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6216         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
6217
6218
6219         /*  */
6220         if (pmlmepriv->num_FortyMHzIntolerant > 0) {
6221                 u8 iedata = 0;
6222
6223                 iedata |= BIT(2);/* 20 MHz BSS Width Request */
6224
6225                 pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
6226         }
6227
6228
6229         /*  */
6230         _rtw_memset(ICS, 0, sizeof(ICS));
6231         if (pmlmepriv->num_sta_no_ht > 0) {
6232                 int i;
6233
6234                 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6235
6236                 phead = get_list_head(queue);
6237                 plist = get_next(phead);
6238
6239                 while (1) {
6240                         int len;
6241                         u8 *p;
6242                         struct wlan_bssid_ex *pbss_network;
6243
6244                         if (rtw_end_of_queue_search(phead, plist))
6245                                 break;
6246
6247                         pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
6248
6249                         plist = get_next(plist);
6250
6251                         pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
6252
6253                         p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
6254                         if ((p == NULL) || (len == 0)) { /* non-HT */
6255                                 if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
6256                                         continue;
6257
6258                                 ICS[0][pbss_network->Configuration.DSConfig] = 1;
6259
6260                                 if (ICS[0][0] == 0)
6261                                         ICS[0][0] = 1;
6262                         }
6263                 }
6264                 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6265
6266                 for (i = 0; i < 8; i++) {
6267                         if (ICS[i][0] == 1) {
6268                                 int j, k = 0;
6269
6270                                 InfoContent[k] = i;
6271                                 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
6272                                 k++;
6273
6274                                 for (j = 1; j <= 14; j++) {
6275                                         if (ICS[i][j] == 1) {
6276                                                 if (k < 16) {
6277                                                         InfoContent[k] = j; /* channel number */
6278                                                         /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
6279                                                         k++;
6280                                                 }
6281                                         }
6282                                 }
6283
6284                                 pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
6285                         }
6286                 }
6287         }
6288
6289
6290         pattrib->last_txcmdsz = pattrib->pktlen;
6291
6292         dump_mgntframe(padapter, pmgntframe);
6293 }
6294
6295 unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
6296 {
6297         struct sta_priv *pstapriv = &padapter->stapriv;
6298         struct sta_info *psta = NULL;
6299         /* struct recv_reorder_ctrl *preorder_ctrl; */
6300         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6301         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6302         u16 tid;
6303
6304         if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
6305                 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
6306                         return _SUCCESS;
6307
6308         psta = rtw_get_stainfo(pstapriv, addr);
6309         if (psta == NULL)
6310                 return _SUCCESS;
6311
6312         if (initiator == 0) { /*  recipient */
6313                 for (tid = 0; tid < MAXTID; tid++) {
6314                         if (psta->recvreorder_ctrl[tid].enable) {
6315                                 DBG_88E("rx agg disable tid(%d)\n", tid);
6316                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
6317                                 psta->recvreorder_ctrl[tid].enable = false;
6318                                 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
6319                         }
6320                 }
6321         } else if (initiator == 1) { /*  originator */
6322                 for (tid = 0; tid < MAXTID; tid++) {
6323                         if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
6324                                 DBG_88E("tx agg disable tid(%d)\n", tid);
6325                                 issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
6326                                 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
6327                                 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
6328                         }
6329                 }
6330         }
6331
6332         return _SUCCESS;
6333 }
6334
6335 unsigned int send_beacon(struct adapter *padapter)
6336 {
6337         u8 bxmitok = false;
6338         int     issue = 0;
6339         int poll = 0;
6340
6341         u32 start = rtw_get_current_time();
6342
6343         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
6344         do {
6345                 issue_beacon(padapter, 100);
6346                 issue++;
6347                 do {
6348                         rtw_yield_os();
6349                         rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
6350                         poll++;
6351                 } while ((poll%10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
6352         } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
6353
6354         if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
6355                 return _FAIL;
6356         if (!bxmitok) {
6357                 DBG_88E("%s fail! %u ms\n", __func__, rtw_get_passing_time_ms(start));
6358                 return _FAIL;
6359         } else {
6360                 u32 passing_time = rtw_get_passing_time_ms(start);
6361
6362                 if (passing_time > 100 || issue > 3)
6363                         DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, rtw_get_passing_time_ms(start));
6364                 return _SUCCESS;
6365         }
6366 }
6367
6368 /****************************************************************************
6369
6370 Following are some utitity fuctions for WiFi MLME
6371
6372 *****************************************************************************/
6373
6374 void site_survey(struct adapter *padapter)
6375 {
6376         unsigned char           survey_channel = 0, val8;
6377         enum rt_scan_type ScanType = SCAN_PASSIVE;
6378         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6379         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6380         u32 initialgain = 0;
6381
6382 #ifdef CONFIG_88EU_P2P
6383         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
6384
6385         if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
6386                 if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
6387                         survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
6388                 } else {
6389                         survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
6390                 }
6391                 ScanType = SCAN_ACTIVE;
6392         } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
6393                 /*      Commented by Albert 2011/06/03 */
6394                 /*      The driver is in the find phase, it should go through the social channel. */
6395                 int ch_set_idx;
6396                 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
6397                 ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
6398                 if (ch_set_idx >= 0)
6399                         ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
6400                 else
6401                         ScanType = SCAN_ACTIVE;
6402         } else
6403 #endif /* CONFIG_88EU_P2P */
6404         {
6405                 struct rtw_ieee80211_channel *ch;
6406                 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
6407                         ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
6408                         survey_channel = ch->hw_value;
6409                         ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
6410                 }
6411         }
6412
6413         if (survey_channel != 0) {
6414                 /* PAUSE 4-AC Queue when site_survey */
6415                 /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
6416                 /* val8 |= 0x0f; */
6417                 /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
6418                 if (pmlmeext->sitesurvey_res.channel_idx == 0)
6419                         set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6420                 else
6421                         SelectChannel(padapter, survey_channel);
6422
6423                 if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
6424                         #ifdef CONFIG_88EU_P2P
6425                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
6426                             rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6427                                 issue_probereq_p2p(padapter, NULL);
6428                                 issue_probereq_p2p(padapter, NULL);
6429                                 issue_probereq_p2p(padapter, NULL);
6430                         } else
6431                         #endif /* CONFIG_88EU_P2P */
6432                         {
6433                                 int i;
6434                                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6435                                         if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
6436                                                 /* todo: to issue two probe req??? */
6437                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
6438                                                 /* rtw_msleep_os(SURVEY_TO>>1); */
6439                                                 issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
6440                                         }
6441                                 }
6442
6443                                 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
6444                                         /* todo: to issue two probe req??? */
6445                                         issue_probereq(padapter, NULL, NULL);
6446                                         /* rtw_msleep_os(SURVEY_TO>>1); */
6447                                         issue_probereq(padapter, NULL, NULL);
6448                                 }
6449                         }
6450                 }
6451
6452                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6453         } else {
6454                 /*      channel number is 0 or this channel is not valid. */
6455
6456 #ifdef CONFIG_88EU_P2P
6457                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6458                         if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
6459                                 /*      Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
6460                                 /*      This will let the following flow to run the scanning end. */
6461                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
6462                         }
6463                 }
6464
6465                 if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
6466                         /*      Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
6467                         set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6468                         rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
6469                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6470
6471                         initialgain = 0xff; /* restore RX GAIN */
6472                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
6473                         /* turn on dynamic functions */
6474                         Restore_DM_Func_Flag(padapter);
6475                         /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
6476
6477                         _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100));
6478                 } else
6479 #endif /* CONFIG_88EU_P2P */
6480                 {
6481                         /*  20100721:Interrupt scan operation here. */
6482                         /*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
6483                         /*  It compares the scan result and select beter one to do connection. */
6484                         if (rtw_hal_antdiv_before_linked(padapter)) {
6485                                 pmlmeext->sitesurvey_res.bss_cnt = 0;
6486                                 pmlmeext->sitesurvey_res.channel_idx = -1;
6487                                 pmlmeext->chan_scan_time = SURVEY_TO / 2;
6488                                 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6489                                 return;
6490                         }
6491 #ifdef CONFIG_88EU_P2P
6492                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
6493                                 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
6494                         rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
6495 #endif /* CONFIG_88EU_P2P */
6496
6497                         pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
6498
6499                         /* switch back to the original channel */
6500
6501 #ifdef CONFIG_88EU_P2P
6502                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
6503                                 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6504                         else
6505                                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6506 #endif /* CONFIG_88EU_P2P */
6507
6508                         /* flush 4-AC Queue after site_survey */
6509                         /* val8 = 0; */
6510                         /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
6511
6512                         /* config MSR */
6513                         Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6514
6515                         initialgain = 0xff; /* restore RX GAIN */
6516                         rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
6517                         /* turn on dynamic functions */
6518                         Restore_DM_Func_Flag(padapter);
6519                         /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
6520
6521                         if (is_client_associated_to_ap(padapter))
6522                                 issue_nulldata(padapter, NULL, 0, 3, 500);
6523
6524                         val8 = 0; /* survey done */
6525                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
6526
6527                         report_surveydone_event(padapter);
6528
6529                         pmlmeext->chan_scan_time = SURVEY_TO;
6530                         pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6531
6532                         issue_action_BSSCoexistPacket(padapter);
6533                         issue_action_BSSCoexistPacket(padapter);
6534                         issue_action_BSSCoexistPacket(padapter);
6535                 }
6536         }
6537         return;
6538 }
6539
6540 /* collect bss info from Beacon and Probe request/response frames. */
6541 u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
6542 {
6543         int     i;
6544         u32     len;
6545         u8 *p;
6546         u16 val16, subtype;
6547         u8 *pframe = precv_frame->u.hdr.rx_data;
6548         u32     packet_len = precv_frame->u.hdr.len;
6549         u8 ie_offset;
6550         struct registry_priv    *pregistrypriv = &padapter->registrypriv;
6551         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6552         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6553         __le32 le32_tmp;
6554
6555         len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
6556
6557         if (len > MAX_IE_SZ)
6558                 return _FAIL;
6559
6560         _rtw_memset(bssid, 0, sizeof(struct wlan_bssid_ex));
6561
6562         subtype = GetFrameSubType(pframe);
6563
6564         if (subtype == WIFI_BEACON) {
6565                 bssid->Reserved[0] = 1;
6566                 ie_offset = _BEACON_IE_OFFSET_;
6567         } else {
6568                 /*  FIXME : more type */
6569                 if (subtype == WIFI_PROBEREQ) {
6570                         ie_offset = _PROBEREQ_IE_OFFSET_;
6571                         bssid->Reserved[0] = 2;
6572                 } else if (subtype == WIFI_PROBERSP) {
6573                         ie_offset = _PROBERSP_IE_OFFSET_;
6574                         bssid->Reserved[0] = 3;
6575                 } else {
6576                         bssid->Reserved[0] = 0;
6577                         ie_offset = _FIXED_IE_LENGTH_;
6578                 }
6579         }
6580
6581         bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
6582
6583         /* below is to copy the information element */
6584         bssid->IELength = len;
6585         memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
6586
6587         /* get the signal strength */
6588         bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.recvpower; /*  in dBM.raw data */
6589         bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
6590         bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
6591         rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
6592
6593         /*  checking SSID */
6594         p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
6595         if (p == NULL) {
6596                 DBG_88E("marc: cannot find SSID for survey event\n");
6597                 return _FAIL;
6598         }
6599
6600         if (*(p + 1)) {
6601                 if (len > NDIS_802_11_LENGTH_SSID) {
6602                         DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
6603                         return _FAIL;
6604                 }
6605                 memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
6606                 bssid->Ssid.SsidLength = *(p + 1);
6607         } else {
6608                 bssid->Ssid.SsidLength = 0;
6609         }
6610
6611         _rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
6612
6613         /* checking rate info... */
6614         i = 0;
6615         p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6616         if (p != NULL) {
6617                 if (len > NDIS_802_11_LENGTH_RATES_EX) {
6618                         DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
6619                         return _FAIL;
6620                 }
6621                 memcpy(bssid->SupportedRates, (p + 2), len);
6622                 i = len;
6623         }
6624
6625         p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6626         if (p != NULL) {
6627                 if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
6628                         DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
6629                         return _FAIL;
6630                 }
6631                 memcpy(bssid->SupportedRates + i, (p + 2), len);
6632         }
6633
6634         /* todo: */
6635         bssid->NetworkTypeInUse = Ndis802_11OFDM24;
6636
6637         if (bssid->IELength < 12)
6638                 return _FAIL;
6639
6640         /*  Checking for DSConfig */
6641         p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
6642
6643         bssid->Configuration.DSConfig = 0;
6644         bssid->Configuration.Length = 0;
6645
6646         if (p) {
6647                 bssid->Configuration.DSConfig = *(p + 2);
6648         } else {/*  In 5G, some ap do not have DSSET IE */
6649                 /*  checking HT info for channel */
6650                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
6651                 if (p) {
6652                         struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
6653                         bssid->Configuration.DSConfig = HT_info->primary_channel;
6654                 } else { /*  use current channel */
6655                         bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
6656                 }
6657         }
6658
6659         if (subtype == WIFI_PROBEREQ) {
6660                 /*  FIXME */
6661                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
6662                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
6663                 bssid->Privacy = 1;
6664                 return _SUCCESS;
6665         }
6666
6667         memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
6668         bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
6669
6670         val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
6671
6672         if (val16 & BIT(0)) {
6673                 bssid->InfrastructureMode = Ndis802_11Infrastructure;
6674                 memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
6675         } else {
6676                 bssid->InfrastructureMode = Ndis802_11IBSS;
6677                 memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
6678         }
6679
6680         if (val16 & BIT(4))
6681                 bssid->Privacy = 1;
6682         else
6683                 bssid->Privacy = 0;
6684
6685         bssid->Configuration.ATIMWindow = 0;
6686
6687         /* 20/40 BSS Coexistence check */
6688         if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
6689                 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6690                 p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
6691                 if (p && len > 0) {
6692                         struct HT_caps_element  *pHT_caps;
6693                         pHT_caps = (struct HT_caps_element *)(p + 2);
6694
6695                         if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info)&BIT(14))
6696                                 pmlmepriv->num_FortyMHzIntolerant++;
6697                 } else {
6698                         pmlmepriv->num_sta_no_ht++;
6699                 }
6700         }
6701
6702         /*  mark bss info receiving from nearby channel as SignalQuality 101 */
6703         if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
6704                 bssid->PhyInfo.SignalQuality = 101;
6705         return _SUCCESS;
6706 }
6707
6708 void start_create_ibss(struct adapter *padapter)
6709 {
6710         unsigned short  caps;
6711         u8 val8;
6712         u8 join_type;
6713         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6714         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6715         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6716         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6717         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6718
6719         /* update wireless mode */
6720         update_wireless_mode(padapter);
6721
6722         /* udpate capability */
6723         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6724         update_capinfo(padapter, caps);
6725         if (caps&cap_IBSS) {/* adhoc master */
6726                 val8 = 0xcf;
6727                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
6728
6729                 /* switch channel */
6730                 /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
6731                 set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6732
6733                 beacon_timing_control(padapter);
6734
6735                 /* set msr to WIFI_FW_ADHOC_STATE */
6736                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6737                 Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6738
6739                 /* issue beacon */
6740                 if (send_beacon(padapter) == _FAIL) {
6741                         RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
6742
6743                         report_join_res(padapter, -1);
6744                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
6745                 } else {
6746                         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
6747                         join_type = 0;
6748                         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
6749
6750                         report_join_res(padapter, 1);
6751                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
6752                 }
6753         } else {
6754                 DBG_88E("start_create_ibss, invalid cap:%x\n", caps);
6755                 return;
6756         }
6757 }
6758
6759 void start_clnt_join(struct adapter *padapter)
6760 {
6761         unsigned short  caps;
6762         u8 val8;
6763         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6764         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6765         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6766         int beacon_timeout;
6767
6768         pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6769         pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6770
6771         /* update wireless mode */
6772         update_wireless_mode(padapter);
6773
6774         /* udpate capability */
6775         caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6776         update_capinfo(padapter, caps);
6777         if (caps&cap_ESS) {
6778                 Set_MSR(padapter, WIFI_FW_STATION_STATE);
6779
6780                 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
6781
6782                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
6783
6784                 /* switch channel */
6785                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6786
6787                 /* here wait for receiving the beacon to start auth */
6788                 /* and enable a timer */
6789                 beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
6790                 set_link_timer(pmlmeext, beacon_timeout);
6791                 _set_timer(&padapter->mlmepriv.assoc_timer,
6792                            (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
6793
6794                 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
6795         } else if (caps&cap_IBSS) { /* adhoc client */
6796                 Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
6797
6798                 val8 = 0xcf;
6799                 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
6800
6801                 /* switch channel */
6802                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6803
6804                 beacon_timing_control(padapter);
6805
6806                 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6807
6808                 report_join_res(padapter, 1);
6809         } else {
6810                 return;
6811         }
6812 }
6813
6814 void start_clnt_auth(struct adapter *padapter)
6815 {
6816         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6817         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6818
6819         _cancel_timer_ex(&pmlmeext->link_timer);
6820
6821         pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
6822         pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
6823
6824         pmlmeinfo->auth_seq = 1;
6825         pmlmeinfo->reauth_count = 0;
6826         pmlmeinfo->reassoc_count = 0;
6827         pmlmeinfo->link_count = 0;
6828         pmlmeext->retry = 0;
6829
6830
6831         /*  Because of AP's not receiving deauth before */
6832         /*  AP may: 1)not response auth or 2)deauth us after link is complete */
6833         /*  issue deauth before issuing auth to deal with the situation */
6834         /*      Commented by Albert 2012/07/21 */
6835         /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
6836         issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
6837
6838         DBG_88E_LEVEL(_drv_info_, "start auth\n");
6839         issue_auth(padapter, NULL, 0);
6840
6841         set_link_timer(pmlmeext, REAUTH_TO);
6842 }
6843
6844
6845 void start_clnt_assoc(struct adapter *padapter)
6846 {
6847         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6848         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6849
6850         _cancel_timer_ex(&pmlmeext->link_timer);
6851
6852         pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
6853         pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
6854
6855         issue_assocreq(padapter);
6856
6857         set_link_timer(pmlmeext, REASSOC_TO);
6858 }
6859
6860 unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
6861 {
6862         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6863         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6864
6865         /* check A3 */
6866         if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
6867                 return _SUCCESS;
6868
6869         DBG_88E("%s\n", __func__);
6870
6871         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
6872                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
6873                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
6874                         report_del_sta_event(padapter, MacAddr, reason);
6875                 } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
6876                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
6877                         report_join_res(padapter, -2);
6878                 }
6879         }
6880         return _SUCCESS;
6881 }
6882
6883 static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
6884 {
6885         struct registry_priv *pregistrypriv;
6886         struct mlme_ext_priv *pmlmeext;
6887         struct rt_channel_info *chplan_new;
6888         u8 channel;
6889         u8 i;
6890
6891         pregistrypriv = &padapter->registrypriv;
6892         pmlmeext = &padapter->mlmeextpriv;
6893
6894         /*  Adjust channel plan by AP Country IE */
6895         if (pregistrypriv->enable80211d &&
6896             (!pmlmeext->update_channel_plan_by_ap_done)) {
6897                 u8 *ie, *p;
6898                 u32 len;
6899                 struct rt_channel_plan chplan_ap;
6900                 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
6901                 u8 country[4];
6902                 u8 fcn; /*  first channel number */
6903                 u8 noc; /*  number of channel */
6904                 u8 j, k;
6905
6906                 ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
6907                 if (!ie)
6908                         return;
6909                 if (len < 6)
6910                         return;
6911                 ie += 2;
6912                 p = ie;
6913                 ie += len;
6914
6915                 _rtw_memset(country, 0, 4);
6916                 memcpy(country, p, 3);
6917                 p += 3;
6918                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
6919                          ("%s: 802.11d country =%s\n", __func__, country));
6920
6921                 i = 0;
6922                 while ((ie - p) >= 3) {
6923                         fcn = *(p++);
6924                         noc = *(p++);
6925                         p++;
6926
6927                         for (j = 0; j < noc; j++) {
6928                                 if (fcn <= 14)
6929                                         channel = fcn + j; /*  2.4 GHz */
6930                                 else
6931                                         channel = fcn + j*4; /*  5 GHz */
6932
6933                                 chplan_ap.Channel[i++] = channel;
6934                         }
6935                 }
6936                 chplan_ap.Len = i;
6937
6938                 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
6939
6940                 _rtw_memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
6941                 chplan_new = pmlmeext->channel_set;
6942
6943                 i = 0;
6944                 j = 0;
6945                 k = 0;
6946                 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
6947                         do {
6948                                 if ((i == MAX_CHANNEL_NUM) ||
6949                                     (chplan_sta[i].ChannelNum == 0) ||
6950                                     (chplan_sta[i].ChannelNum > 14))
6951                                         break;
6952
6953                                 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
6954                                         break;
6955
6956                                 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
6957                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6958                                         chplan_new[k].ScanType = SCAN_ACTIVE;
6959                                         i++;
6960                                         j++;
6961                                         k++;
6962                                 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
6963                                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6964                                         chplan_new[k].ScanType = SCAN_PASSIVE;
6965                                         i++;
6966                                         k++;
6967                                 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
6968                                         chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6969                                         chplan_new[k].ScanType = SCAN_ACTIVE;
6970                                         j++;
6971                                         k++;
6972                                 }
6973                         } while (1);
6974
6975                         /*  change AP not support channel to Passive scan */
6976                         while ((i < MAX_CHANNEL_NUM) &&
6977                                (chplan_sta[i].ChannelNum != 0) &&
6978                                (chplan_sta[i].ChannelNum <= 14)) {
6979                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6980                                 chplan_new[k].ScanType = SCAN_PASSIVE;
6981                                 i++;
6982                                 k++;
6983                         }
6984
6985                         /*  add channel AP supported */
6986                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
6987                                 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6988                                 chplan_new[k].ScanType = SCAN_ACTIVE;
6989                                 j++;
6990                                 k++;
6991                         }
6992                 } else {
6993                         /*  keep original STA 2.4G channel plan */
6994                         while ((i < MAX_CHANNEL_NUM) &&
6995                                (chplan_sta[i].ChannelNum != 0) &&
6996                                (chplan_sta[i].ChannelNum <= 14)) {
6997                                 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6998                                 chplan_new[k].ScanType = chplan_sta[i].ScanType;
6999                                 i++;
7000                                 k++;
7001                         }
7002
7003                         /*  skip AP 2.4G channel plan */
7004                         while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
7005                                 j++;
7006                 }
7007
7008                 /*  keep original STA 5G channel plan */
7009                 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
7010                         chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
7011                         chplan_new[k].ScanType = chplan_sta[i].ScanType;
7012                         i++;
7013                         k++;
7014                 }
7015
7016                 pmlmeext->update_channel_plan_by_ap_done = 1;
7017         }
7018
7019         /*  If channel is used by AP, set channel scan type to active */
7020         channel = bssid->Configuration.DSConfig;
7021         chplan_new = pmlmeext->channel_set;
7022         i = 0;
7023         while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
7024                 if (chplan_new[i].ChannelNum == channel) {
7025                         if (chplan_new[i].ScanType == SCAN_PASSIVE) {
7026                                 chplan_new[i].ScanType = SCAN_ACTIVE;
7027                                 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
7028                                          ("%s: change channel %d scan type from passive to active\n",
7029                                          __func__, channel));
7030                         }
7031                         break;
7032                 }
7033                 i++;
7034         }
7035 }
7036
7037 /****************************************************************************
7038
7039 Following are the functions to report events
7040
7041 *****************************************************************************/
7042
7043 void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
7044 {
7045         struct cmd_obj *pcmd_obj;
7046         u8 *pevtcmd;
7047         u32 cmdsz;
7048         struct survey_event     *psurvey_evt;
7049         struct C2HEvent_Header *pc2h_evt_hdr;
7050         struct mlme_ext_priv *pmlmeext;
7051         struct cmd_priv *pcmdpriv;
7052         /* u8 *pframe = precv_frame->u.hdr.rx_data; */
7053         /* uint len = precv_frame->u.hdr.len; */
7054
7055         if (!padapter)
7056                 return;
7057
7058         pmlmeext = &padapter->mlmeextpriv;
7059         pcmdpriv = &padapter->cmdpriv;
7060
7061
7062         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7063         if (pcmd_obj == NULL)
7064                 return;
7065
7066         cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
7067         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7068         if (pevtcmd == NULL) {
7069                 kfree(pcmd_obj);
7070                 return;
7071         }
7072
7073         _rtw_init_listhead(&pcmd_obj->list);
7074
7075         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7076         pcmd_obj->cmdsz = cmdsz;
7077         pcmd_obj->parmbuf = pevtcmd;
7078
7079         pcmd_obj->rsp = NULL;
7080         pcmd_obj->rspsz  = 0;
7081
7082         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7083         pc2h_evt_hdr->len = sizeof(struct survey_event);
7084         pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
7085         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7086
7087         psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7088
7089         if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
7090                 kfree(pcmd_obj);
7091                 kfree(pevtcmd);
7092                 return;
7093         }
7094
7095         process_80211d(padapter, &psurvey_evt->bss);
7096
7097         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7098
7099         pmlmeext->sitesurvey_res.bss_cnt++;
7100
7101         return;
7102 }
7103
7104 void report_surveydone_event(struct adapter *padapter)
7105 {
7106         struct cmd_obj *pcmd_obj;
7107         u8 *pevtcmd;
7108         u32 cmdsz;
7109         struct surveydone_event *psurveydone_evt;
7110         struct C2HEvent_Header  *pc2h_evt_hdr;
7111         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7112         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7113
7114         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7115         if (pcmd_obj == NULL)
7116                 return;
7117
7118         cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
7119         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7120         if (pevtcmd == NULL) {
7121                 kfree(pcmd_obj);
7122                 return;
7123         }
7124
7125         _rtw_init_listhead(&pcmd_obj->list);
7126
7127         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7128         pcmd_obj->cmdsz = cmdsz;
7129         pcmd_obj->parmbuf = pevtcmd;
7130
7131         pcmd_obj->rsp = NULL;
7132         pcmd_obj->rspsz  = 0;
7133
7134         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7135         pc2h_evt_hdr->len = sizeof(struct surveydone_event);
7136         pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
7137         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7138
7139         psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7140         psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
7141
7142         DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt);
7143
7144         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7145
7146         return;
7147 }
7148
7149 void report_join_res(struct adapter *padapter, int res)
7150 {
7151         struct cmd_obj *pcmd_obj;
7152         u8 *pevtcmd;
7153         u32 cmdsz;
7154         struct joinbss_event            *pjoinbss_evt;
7155         struct C2HEvent_Header  *pc2h_evt_hdr;
7156         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7157         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7158         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7159
7160         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7161         if (pcmd_obj == NULL)
7162                 return;
7163
7164         cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
7165         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7166         if (pevtcmd == NULL) {
7167                 kfree(pcmd_obj);
7168                 return;
7169         }
7170
7171         _rtw_init_listhead(&pcmd_obj->list);
7172
7173         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7174         pcmd_obj->cmdsz = cmdsz;
7175         pcmd_obj->parmbuf = pevtcmd;
7176
7177         pcmd_obj->rsp = NULL;
7178         pcmd_obj->rspsz  = 0;
7179
7180         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7181         pc2h_evt_hdr->len = sizeof(struct joinbss_event);
7182         pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
7183         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7184
7185         pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7186         memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
7187         pjoinbss_evt->network.join_res  = res;
7188         pjoinbss_evt->network.aid = res;
7189
7190         DBG_88E("report_join_res(%d)\n", res);
7191
7192
7193         rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
7194
7195
7196         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7197
7198         return;
7199 }
7200
7201 void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
7202 {
7203         struct cmd_obj *pcmd_obj;
7204         u8 *pevtcmd;
7205         u32 cmdsz;
7206         struct sta_info *psta;
7207         int     mac_id;
7208         struct stadel_event                     *pdel_sta_evt;
7209         struct C2HEvent_Header  *pc2h_evt_hdr;
7210         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7211         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7212
7213         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7214         if (pcmd_obj == NULL)
7215                 return;
7216
7217         cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
7218         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7219         if (pevtcmd == NULL) {
7220                 kfree(pcmd_obj);
7221                 return;
7222         }
7223
7224         _rtw_init_listhead(&pcmd_obj->list);
7225
7226         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7227         pcmd_obj->cmdsz = cmdsz;
7228         pcmd_obj->parmbuf = pevtcmd;
7229
7230         pcmd_obj->rsp = NULL;
7231         pcmd_obj->rspsz  = 0;
7232
7233         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7234         pc2h_evt_hdr->len = sizeof(struct stadel_event);
7235         pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
7236         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7237
7238         pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7239         memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
7240         memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
7241
7242
7243         psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
7244         if (psta)
7245                 mac_id = (int)psta->mac_id;
7246         else
7247                 mac_id = (-1);
7248
7249         pdel_sta_evt->mac_id = mac_id;
7250
7251         DBG_88E("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
7252
7253         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7254
7255         return;
7256 }
7257
7258 void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
7259 {
7260         struct cmd_obj *pcmd_obj;
7261         u8 *pevtcmd;
7262         u32 cmdsz;
7263         struct stassoc_event            *padd_sta_evt;
7264         struct C2HEvent_Header  *pc2h_evt_hdr;
7265         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7266         struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7267
7268         pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7269         if (pcmd_obj == NULL)
7270                 return;
7271
7272         cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
7273         pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7274         if (pevtcmd == NULL) {
7275                 kfree(pcmd_obj);
7276                 return;
7277         }
7278
7279         _rtw_init_listhead(&pcmd_obj->list);
7280
7281         pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7282         pcmd_obj->cmdsz = cmdsz;
7283         pcmd_obj->parmbuf = pevtcmd;
7284
7285         pcmd_obj->rsp = NULL;
7286         pcmd_obj->rspsz  = 0;
7287
7288         pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7289         pc2h_evt_hdr->len = sizeof(struct stassoc_event);
7290         pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
7291         pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7292
7293         padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7294         memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
7295         padd_sta_evt->cam_id = cam_idx;
7296
7297         DBG_88E("report_add_sta_event: add STA\n");
7298
7299         rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7300
7301         return;
7302 }
7303
7304
7305 /****************************************************************************
7306
7307 Following are the event callback functions
7308
7309 *****************************************************************************/
7310
7311 /* for sta/adhoc mode */
7312 void update_sta_info(struct adapter *padapter, struct sta_info *psta)
7313 {
7314         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7315         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7316         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7317
7318         /* ERP */
7319         VCS_update(padapter, psta);
7320
7321         /* HT */
7322         if (pmlmepriv->htpriv.ht_option) {
7323                 psta->htpriv.ht_option = true;
7324
7325                 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
7326
7327                 if (support_short_GI(padapter, &(pmlmeinfo->HT_caps)))
7328                         psta->htpriv.sgi = true;
7329
7330                 psta->qos_option = true;
7331         } else {
7332                 psta->htpriv.ht_option = false;
7333
7334                 psta->htpriv.ampdu_enable = false;
7335
7336                 psta->htpriv.sgi = false;
7337                 psta->qos_option = false;
7338         }
7339         psta->htpriv.bwmode = pmlmeext->cur_bwmode;
7340         psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
7341
7342         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
7343         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
7344
7345         /* QoS */
7346         if (pmlmepriv->qospriv.qos_option)
7347                 psta->qos_option = true;
7348
7349
7350         psta->state = _FW_LINKED;
7351 }
7352
7353 void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
7354 {
7355         struct sta_info         *psta, *psta_bmc;
7356         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7357         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7358         struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
7359         struct sta_priv         *pstapriv = &padapter->stapriv;
7360         u8 join_type;
7361         u16 media_status;
7362
7363         if (join_res < 0) {
7364                 join_type = 1;
7365                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7366                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
7367
7368                 /* restore to initial setting. */
7369                 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7370
7371                 goto exit_mlmeext_joinbss_event_callback;
7372         }
7373
7374         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
7375                 /* for bc/mc */
7376                 psta_bmc = rtw_get_bcmc_stainfo(padapter);
7377                 if (psta_bmc) {
7378                         pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
7379                         update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
7380                         Update_RA_Entry(padapter, psta_bmc->mac_id);
7381                 }
7382         }
7383
7384
7385         /* turn on dynamic functions */
7386         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
7387
7388         /*  update IOT-releated issue */
7389         update_IOT_info(padapter);
7390
7391         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
7392
7393         /* BCN interval */
7394         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
7395
7396         /* udpate capability */
7397         update_capinfo(padapter, pmlmeinfo->capability);
7398
7399         /* WMM, Update EDCA param */
7400         WMMOnAssocRsp(padapter);
7401
7402         /* HT */
7403         HTOnAssocRsp(padapter);
7404
7405         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7406
7407         psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
7408         if (psta) { /* only for infra. mode */
7409                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
7410
7411                 psta->wireless_mode = pmlmeext->cur_wireless_mode;
7412
7413                 /* set per sta rate after updating HT cap. */
7414                 set_sta_rate(padapter, psta);
7415                 rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
7416                 media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE: 1 means connect */
7417                 rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
7418         }
7419
7420         join_type = 2;
7421         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7422
7423         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
7424                 /*  correcting TSF */
7425                 correct_TSF(padapter, pmlmeext);
7426         }
7427         rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
7428
7429 exit_mlmeext_joinbss_event_callback:
7430
7431         DBG_88E("=>%s\n", __func__);
7432 }
7433
7434 void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
7435 {
7436         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7437         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7438         u8 join_type;
7439
7440         DBG_88E("%s\n", __func__);
7441
7442         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
7443                 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
7444                         /* nothing to do */
7445                 } else { /* adhoc client */
7446                         /*  correcting TSF */
7447                         correct_TSF(padapter, pmlmeext);
7448
7449                         /* start beacon */
7450                         if (send_beacon(padapter) == _FAIL) {
7451                                 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
7452                                 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
7453                                 return;
7454                         }
7455                         pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
7456                 }
7457
7458                 join_type = 2;
7459                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7460         }
7461
7462         pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
7463
7464         /* rate radaptive */
7465         Update_RA_Entry(padapter, psta->mac_id);
7466
7467         /* update adhoc sta_info */
7468         update_sta_info(padapter, psta);
7469 }
7470
7471 void mlmeext_sta_del_event_callback(struct adapter *padapter)
7472 {
7473         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7474         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7475
7476         if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
7477                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
7478                 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
7479
7480                 /* restore to initial setting. */
7481                 update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7482
7483                 /* switch to the 20M Hz mode after disconnect */
7484                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7485                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7486
7487                 /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
7488                 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7489
7490
7491                 flush_all_cam_entry(padapter);
7492
7493                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7494
7495                 /* set MSR to no link state -> infra. mode */
7496                 Set_MSR(padapter, _HW_STATE_STATION_);
7497
7498                 _cancel_timer_ex(&pmlmeext->link_timer);
7499         }
7500 }
7501
7502 /****************************************************************************
7503
7504 Following are the functions for the timer handlers
7505
7506 *****************************************************************************/
7507 void _linked_rx_signal_strehgth_display(struct adapter *padapter);
7508 void _linked_rx_signal_strehgth_display(struct adapter *padapter)
7509 {
7510         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7511       struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7512         u8 mac_id;
7513         int UndecoratedSmoothedPWDB;
7514         if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
7515                 mac_id = 0;
7516         else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
7517                 mac_id = 2;
7518
7519         rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &mac_id);
7520
7521         rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
7522         DBG_88E("UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
7523 }
7524
7525 static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
7526 {
7527         u8 ret = false;
7528
7529         if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
7530             sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
7531             sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
7532                 ret = false;
7533         else
7534                 ret = true;
7535
7536         sta_update_last_rx_pkts(psta);
7537
7538         return ret;
7539 }
7540
7541 void linked_status_chk(struct adapter *padapter)
7542 {
7543         u32     i;
7544         struct sta_info         *psta;
7545         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7546         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7547         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7548         struct sta_priv         *pstapriv = &padapter->stapriv;
7549
7550         if (padapter->bRxRSSIDisplay)
7551                 _linked_rx_signal_strehgth_display(padapter);
7552
7553         rtw_hal_sreset_linked_status_check(padapter);
7554
7555         if (is_client_associated_to_ap(padapter)) {
7556                 /* linked infrastructure client mode */
7557
7558                 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
7559                 int rx_chk_limit;
7560
7561                 rx_chk_limit = 4;
7562                 psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
7563                 if (psta != NULL) {
7564                         bool is_p2p_enable = false;
7565                         #ifdef CONFIG_88EU_P2P
7566                         is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
7567                         #endif
7568
7569                         if (!chk_ap_is_alive(padapter, psta))
7570                                 rx_chk = _FAIL;
7571
7572                         if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
7573                                 tx_chk = _FAIL;
7574
7575                         if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
7576                                 u8 backup_oper_channel = 0;
7577
7578                                 /* switch to correct channel of current network  before issue keep-alive frames */
7579                                 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
7580                                         backup_oper_channel = rtw_get_oper_ch(padapter);
7581                                         SelectChannel(padapter, pmlmeext->cur_channel);
7582                                 }
7583
7584                                 if (rx_chk != _SUCCESS)
7585                                         issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
7586
7587                                 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
7588                                         tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
7589                                         /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
7590                                         if (tx_chk == _SUCCESS && !is_p2p_enable)
7591                                                 rx_chk = _SUCCESS;
7592                                 }
7593
7594                                 /* back to the original operation channel */
7595                                 if (backup_oper_channel > 0)
7596                                         SelectChannel(padapter, backup_oper_channel);
7597                         } else {
7598                                 if (rx_chk != _SUCCESS) {
7599                                         if (pmlmeext->retry == 0) {
7600                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7601                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7602                                                 issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7603                                         }
7604                                 }
7605
7606                                 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
7607                                         tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
7608                                 }
7609                         }
7610
7611                         if (rx_chk == _FAIL) {
7612                                 pmlmeext->retry++;
7613                                 if (pmlmeext->retry > rx_chk_limit) {
7614                                         DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
7615                                                       FUNC_ADPT_ARG(padapter));
7616                                         receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
7617                                                            WLAN_REASON_EXPIRATION_CHK);
7618                                         return;
7619                                 }
7620                         } else {
7621                                 pmlmeext->retry = 0;
7622                         }
7623
7624                         if (tx_chk == _FAIL) {
7625                                 pmlmeinfo->link_count &= 0xf;
7626                         } else {
7627                                 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
7628                                 pmlmeinfo->link_count = 0;
7629                         }
7630                 } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
7631         } else if (is_client_associated_to_ibss(padapter)) {
7632                 /* linked IBSS mode */
7633                 /* for each assoc list entry to check the rx pkt counter */
7634                 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
7635                         if (pmlmeinfo->FW_sta_info[i].status == 1) {
7636                                 psta = pmlmeinfo->FW_sta_info[i].psta;
7637
7638                                 if (NULL == psta)
7639                                         continue;
7640                                 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
7641                                         if (pmlmeinfo->FW_sta_info[i].retry < 3) {
7642                                                 pmlmeinfo->FW_sta_info[i].retry++;
7643                                         } else {
7644                                                 pmlmeinfo->FW_sta_info[i].retry = 0;
7645                                                 pmlmeinfo->FW_sta_info[i].status = 0;
7646                                                 report_del_sta_event(padapter, psta->hwaddr
7647                                                         , 65535/*  indicate disconnect caused by no rx */
7648                                         );
7649                                         }
7650                                 } else {
7651                                         pmlmeinfo->FW_sta_info[i].retry = 0;
7652                                         pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
7653                                 }
7654                         }
7655                 }
7656         }
7657 }
7658
7659 void survey_timer_hdl(struct adapter *padapter)
7660 {
7661         struct cmd_obj  *ph2c;
7662         struct sitesurvey_parm  *psurveyPara;
7663         struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
7664         struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7665 #ifdef CONFIG_88EU_P2P
7666         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
7667 #endif
7668
7669         /* issue rtw_sitesurvey_cmd */
7670         if (pmlmeext->sitesurvey_res.state > SCAN_START) {
7671                 if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
7672                         pmlmeext->sitesurvey_res.channel_idx++;
7673
7674                 if (pmlmeext->scan_abort) {
7675                         #ifdef CONFIG_88EU_P2P
7676                         if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
7677                                 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
7678                                 pmlmeext->sitesurvey_res.channel_idx = 3;
7679                                 DBG_88E("%s idx:%d, cnt:%u\n", __func__
7680                                         , pmlmeext->sitesurvey_res.channel_idx
7681                                         , pwdinfo->find_phase_state_exchange_cnt
7682                         );
7683                         } else
7684                         #endif
7685                         {
7686                                 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
7687                                 DBG_88E("%s idx:%d\n", __func__
7688                                         , pmlmeext->sitesurvey_res.channel_idx
7689                         );
7690                         }
7691
7692                         pmlmeext->scan_abort = false;/* reset */
7693                 }
7694
7695                 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7696                 if (ph2c == NULL)
7697                         goto exit_survey_timer_hdl;
7698
7699                 psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
7700                 if (psurveyPara == NULL) {
7701                         kfree(ph2c);
7702                         goto exit_survey_timer_hdl;
7703                 }
7704
7705                 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
7706                 rtw_enqueue_cmd(pcmdpriv, ph2c);
7707         }
7708
7709
7710 exit_survey_timer_hdl:
7711         return;
7712 }
7713
7714 void link_timer_hdl(struct adapter *padapter)
7715 {
7716         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7717         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7718
7719         if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
7720                 DBG_88E("link_timer_hdl:no beacon while connecting\n");
7721                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7722                 report_join_res(padapter, -3);
7723         } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
7724                 /* re-auth timer */
7725                 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
7726                         pmlmeinfo->state = 0;
7727                         report_join_res(padapter, -1);
7728                         return;
7729                 }
7730
7731                 DBG_88E("link_timer_hdl: auth timeout and try again\n");
7732                 pmlmeinfo->auth_seq = 1;
7733                 issue_auth(padapter, NULL, 0);
7734                 set_link_timer(pmlmeext, REAUTH_TO);
7735         } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
7736                 /* re-assoc timer */
7737                 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
7738                         pmlmeinfo->state = WIFI_FW_NULL_STATE;
7739                         report_join_res(padapter, -2);
7740                         return;
7741                 }
7742
7743                 DBG_88E("link_timer_hdl: assoc timeout and try again\n");
7744                 issue_assocreq(padapter);
7745                 set_link_timer(pmlmeext, REASSOC_TO);
7746         }
7747         return;
7748 }
7749
7750 void addba_timer_hdl(struct sta_info *psta)
7751 {
7752         struct ht_priv  *phtpriv;
7753
7754         if (!psta)
7755                 return;
7756
7757         phtpriv = &psta->htpriv;
7758
7759         if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
7760                 if (phtpriv->candidate_tid_bitmap)
7761                         phtpriv->candidate_tid_bitmap = 0x0;
7762         }
7763 }
7764
7765 u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
7766 {
7767         return H2C_SUCCESS;
7768 }
7769
7770 u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
7771 {
7772         u8 type;
7773         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7774         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7775         struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
7776
7777         if (psetop->mode == Ndis802_11APMode) {
7778                 pmlmeinfo->state = WIFI_FW_AP_STATE;
7779                 type = _HW_STATE_AP_;
7780         } else if (psetop->mode == Ndis802_11Infrastructure) {
7781                 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
7782                 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
7783                 type = _HW_STATE_STATION_;
7784         } else if (psetop->mode == Ndis802_11IBSS) {
7785                 type = _HW_STATE_ADHOC_;
7786         } else {
7787                 type = _HW_STATE_NOLINK_;
7788         }
7789
7790         rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
7791         /* Set_NETYPE0_MSR(padapter, type); */
7792
7793         return H2C_SUCCESS;
7794 }
7795
7796 u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
7797 {
7798         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7799         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7800         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
7801         struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
7802         /* u32  initialgain; */
7803
7804
7805         if (pparm->network.InfrastructureMode == Ndis802_11APMode) {
7806 #ifdef CONFIG_88EU_AP_MODE
7807
7808                 if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
7809                         /* todo: */
7810                         return H2C_SUCCESS;
7811                 }
7812 #endif
7813         }
7814
7815         /* below is for ad-hoc master */
7816         if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
7817                 rtw_joinbss_reset(padapter);
7818
7819                 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7820                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7821                 pmlmeinfo->ERP_enable = 0;
7822                 pmlmeinfo->WMM_enable = 0;
7823                 pmlmeinfo->HT_enable = 0;
7824                 pmlmeinfo->HT_caps_enable = 0;
7825                 pmlmeinfo->HT_info_enable = 0;
7826                 pmlmeinfo->agg_enable_bitmap = 0;
7827                 pmlmeinfo->candidate_tid_bitmap = 0;
7828
7829                 /* disable dynamic functions, such as high power, DIG */
7830                 Save_DM_Func_Flag(padapter);
7831                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
7832
7833                 /* config the initial gain under linking, need to write the BB registers */
7834                 /* initialgain = 0x1E; */
7835                 /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
7836
7837                 /* cancel link timer */
7838                 _cancel_timer_ex(&pmlmeext->link_timer);
7839
7840                 /* clear CAM */
7841                 flush_all_cam_entry(padapter);
7842
7843                 memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
7844                 pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7845
7846                 if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7847                         return H2C_PARAMETERS_ERROR;
7848
7849                 memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7850
7851                 start_create_ibss(padapter);
7852         }
7853
7854         return H2C_SUCCESS;
7855 }
7856
7857 u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
7858 {
7859         u8 join_type;
7860         struct ndis_802_11_var_ie *pIE;
7861         struct registry_priv    *pregpriv = &padapter->registrypriv;
7862         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7863         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7864         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
7865         struct joinbss_parm     *pparm = (struct joinbss_parm *)pbuf;
7866         u32 i;
7867
7868         /* check already connecting to AP or not */
7869         if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
7870                 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
7871                         issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
7872
7873                 pmlmeinfo->state = WIFI_FW_NULL_STATE;
7874
7875                 /* clear CAM */
7876                 flush_all_cam_entry(padapter);
7877
7878                 _cancel_timer_ex(&pmlmeext->link_timer);
7879
7880                 /* set MSR to nolink -> infra. mode */
7881                 Set_MSR(padapter, _HW_STATE_STATION_);
7882
7883
7884                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
7885         }
7886
7887         rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false);
7888
7889         rtw_joinbss_reset(padapter);
7890
7891         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7892         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7893         pmlmeinfo->ERP_enable = 0;
7894         pmlmeinfo->WMM_enable = 0;
7895         pmlmeinfo->HT_enable = 0;
7896         pmlmeinfo->HT_caps_enable = 0;
7897         pmlmeinfo->HT_info_enable = 0;
7898         pmlmeinfo->agg_enable_bitmap = 0;
7899         pmlmeinfo->candidate_tid_bitmap = 0;
7900         pmlmeinfo->bwmode_updated = false;
7901
7902         memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
7903         pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7904
7905         if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7906                 return H2C_PARAMETERS_ERROR;
7907
7908         memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7909
7910         /* Check AP vendor to move rtw_joinbss_cmd() */
7911
7912         for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
7913                 pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
7914
7915                 switch (pIE->ElementID) {
7916                 case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
7917                         if (_rtw_memcmp(pIE->data, WMM_OUI, 4))
7918                                 pmlmeinfo->WMM_enable = 1;
7919                         break;
7920                 case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
7921                         pmlmeinfo->HT_caps_enable = 1;
7922                         break;
7923                 case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
7924                         pmlmeinfo->HT_info_enable = 1;
7925
7926                         /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
7927                         {
7928                                 struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
7929
7930                                 if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2))) {
7931                                         /* switch to the 40M Hz mode according to the AP */
7932                                         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
7933                                         switch (pht_info->infos[0] & 0x3) {
7934                                         case 1:
7935                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
7936                                                 break;
7937                                         case 3:
7938                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
7939                                                 break;
7940                                         default:
7941                                                 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7942                                                 break;
7943                                 }
7944
7945                                         DBG_88E("set ch/bw before connected\n");
7946                                 }
7947                         }
7948                         break;
7949                 default:
7950                         break;
7951                 }
7952
7953                 i += (pIE->Length + 2);
7954         }
7955         /* disable dynamic functions, such as high power, DIG */
7956
7957         /* config the initial gain under linking, need to write the BB registers */
7958
7959         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
7960         join_type = 0;
7961         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7962
7963         /* cancel link timer */
7964         _cancel_timer_ex(&pmlmeext->link_timer);
7965
7966         start_clnt_join(padapter);
7967
7968         return H2C_SUCCESS;
7969 }
7970
7971 u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
7972 {
7973         struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
7974         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7975         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7976         struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
7977         u8 val8;
7978
7979         if (is_client_associated_to_ap(padapter))
7980                 issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
7981
7982         rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
7983         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
7984
7985         /* restore to initial setting. */
7986         update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7987
7988         if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
7989                 /* Stop BCN */
7990                 val8 = 0;
7991                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
7992         }
7993
7994
7995         /* set MSR to no link state -> infra. mode */
7996         Set_MSR(padapter, _HW_STATE_STATION_);
7997
7998         pmlmeinfo->state = WIFI_FW_NULL_STATE;
7999
8000         /* switch to the 20M Hz mode after disconnect */
8001         pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
8002         pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
8003
8004         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8005
8006         flush_all_cam_entry(padapter);
8007
8008         _cancel_timer_ex(&pmlmeext->link_timer);
8009
8010         rtw_free_uc_swdec_pending_queue(padapter);
8011
8012         return  H2C_SUCCESS;
8013 }
8014
8015 static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
8016         u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
8017 {
8018         int i, j;
8019         int set_idx;
8020         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8021
8022         /* clear out first */
8023         _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
8024
8025         /* acquire channels from in */
8026         j = 0;
8027         for (i = 0; i < in_num; i++) {
8028                 set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
8029                 if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
8030                     set_idx >= 0) {
8031                         memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
8032
8033                         if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
8034                                 out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
8035
8036                         j++;
8037                 }
8038                 if (j >= out_num)
8039                         break;
8040         }
8041
8042         /* if out is empty, use channel_set as default */
8043         if (j == 0) {
8044                 for (i = 0; i < pmlmeext->max_chan_nums; i++) {
8045                         out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
8046
8047                         if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
8048                                 out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
8049
8050                         j++;
8051                 }
8052         }
8053
8054         return j;
8055 }
8056
8057 u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
8058 {
8059         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8060         struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
8061         u8 bdelayscan = false;
8062         u8 val8;
8063         u32     initialgain;
8064         u32     i;
8065
8066 #ifdef CONFIG_88EU_P2P
8067         struct wifidirect_info *pwdinfo = &padapter->wdinfo;
8068 #endif
8069
8070         if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
8071                 /* for first time sitesurvey_cmd */
8072                 rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
8073
8074                 pmlmeext->sitesurvey_res.state = SCAN_START;
8075                 pmlmeext->sitesurvey_res.bss_cnt = 0;
8076                 pmlmeext->sitesurvey_res.channel_idx = 0;
8077
8078                 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
8079                         if (pparm->ssid[i].SsidLength) {
8080                                 memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
8081                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
8082                         } else {
8083                                 pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
8084                         }
8085                 }
8086
8087                 pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
8088                         , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
8089                         , pparm->ch, pparm->ch_num
8090         );
8091
8092                 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
8093
8094                 /* issue null data if associating to the AP */
8095                 if (is_client_associated_to_ap(padapter)) {
8096                         pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
8097
8098                         issue_nulldata(padapter, NULL, 1, 3, 500);
8099
8100                         bdelayscan = true;
8101                 }
8102                 if (bdelayscan) {
8103                         /* delay 50ms to protect nulldata(1). */
8104                         set_survey_timer(pmlmeext, 50);
8105                         return H2C_SUCCESS;
8106                 }
8107         }
8108
8109         if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
8110                 /* disable dynamic functions, such as high power, DIG */
8111                 Save_DM_Func_Flag(padapter);
8112                 Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
8113
8114                 /* config the initial gain under scanning, need to write the BB registers */
8115 #ifdef CONFIG_88EU_P2P
8116                 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
8117                         initialgain = 0x1E;
8118                 else
8119                         initialgain = 0x28;
8120 #else   /*  CONFIG_88EU_P2P */
8121                 initialgain = 0x1E;
8122 #endif /*  CONFIG_88EU_P2P */
8123
8124                 rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
8125
8126                 /* set MSR to no link state */
8127                 Set_MSR(padapter, _HW_STATE_NOLINK_);
8128
8129                 val8 = 1; /* under site survey */
8130                 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
8131
8132                 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
8133         }
8134
8135         site_survey(padapter);
8136
8137         return H2C_SUCCESS;
8138 }
8139
8140 u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
8141 {
8142         struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
8143         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8144         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8145
8146         if (pparm->mode < 4)
8147                 pmlmeinfo->auth_algo = pparm->mode;
8148         return  H2C_SUCCESS;
8149 }
8150
8151 u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
8152 {
8153         unsigned short                          ctrl;
8154         struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
8155         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8156         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8157         unsigned char                                   null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
8158
8159         /* main tx key for wep. */
8160         if (pparm->set_tx)
8161                 pmlmeinfo->key_index = pparm->keyid;
8162
8163         /* write cam */
8164         ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
8165
8166         DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
8167                         "keyid:%d\n", pparm->algorithm, pparm->keyid);
8168         write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
8169
8170         return H2C_SUCCESS;
8171 }
8172
8173 u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
8174 {
8175         u16 ctrl = 0;
8176         u8 cam_id;/* cam_entry */
8177         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8178         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8179         struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
8180
8181         /* cam_entry: */
8182         /* 0~3 for default key */
8183
8184         /* for concurrent mode (ap+sta): */
8185         /* default key is disable, using sw encrypt/decrypt */
8186         /* cam_entry = 4 for sta mode (macid = 0) */
8187         /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
8188
8189         /* for concurrent mode (sta+sta): */
8190         /* default key is disable, using sw encrypt/decrypt */
8191         /* cam_entry = 4 mapping to macid = 0 */
8192         /* cam_entry = 5 mapping to macid = 2 */
8193
8194         cam_id = 4;
8195
8196         DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
8197                       pparm->algorithm, cam_id);
8198         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
8199                 struct sta_info *psta;
8200                 struct sta_priv *pstapriv = &padapter->stapriv;
8201
8202                 if (pparm->algorithm == _NO_PRIVACY_)   /*  clear cam entry */ {
8203                         clear_cam_entry(padapter, pparm->id);
8204                         return H2C_SUCCESS_RSP;
8205                 }
8206
8207                 psta = rtw_get_stainfo(pstapriv, pparm->addr);
8208                 if (psta) {
8209                         ctrl = (BIT(15) | ((pparm->algorithm) << 2));
8210
8211                         DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
8212
8213                         if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA-4))) {
8214                                 DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
8215                                 return H2C_REJECTED;
8216                         }
8217
8218                         cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
8219
8220                         DBG_88E("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry=%d\n", pparm->addr[0],
8221                                 pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
8222                                 pparm->addr[5], cam_id);
8223
8224                         write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
8225
8226                         return H2C_SUCCESS_RSP;
8227                 } else {
8228                         DBG_88E("r871x_set_stakey_hdl(): sta has been free\n");
8229                         return H2C_REJECTED;
8230                 }
8231         }
8232
8233         /* below for sta mode */
8234
8235         if (pparm->algorithm == _NO_PRIVACY_) { /*  clear cam entry */
8236                 clear_cam_entry(padapter, pparm->id);
8237                 return H2C_SUCCESS;
8238         }
8239         ctrl = BIT(15) | ((pparm->algorithm) << 2);
8240         write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
8241         pmlmeinfo->enc_algo = pparm->algorithm;
8242         return H2C_SUCCESS;
8243 }
8244
8245 u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
8246 {
8247         struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
8248         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8249         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8250
8251         struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
8252
8253         if (!psta)
8254                 return  H2C_SUCCESS;
8255
8256         if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
8257             ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
8258                 issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
8259                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
8260         } else {
8261                 psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
8262         }
8263         return  H2C_SUCCESS;
8264 }
8265
8266 u8 set_tx_beacon_cmd(struct adapter *padapter)
8267 {
8268         struct cmd_obj  *ph2c;
8269         struct Tx_Beacon_param  *ptxBeacon_parm;
8270         struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
8271         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8272         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8273         u8 res = _SUCCESS;
8274         int len_diff = 0;
8275
8276 _func_enter_;
8277
8278         ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
8279         if (ph2c == NULL) {
8280                 res = _FAIL;
8281                 goto exit;
8282         }
8283
8284         ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));
8285         if (ptxBeacon_parm == NULL) {
8286                 kfree(ph2c);
8287                 res = _FAIL;
8288                 goto exit;
8289         }
8290
8291         memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
8292
8293         len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
8294                                       ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
8295                                       pmlmeinfo->hidden_ssid_mode);
8296         ptxBeacon_parm->network.IELength += len_diff;
8297
8298         init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
8299
8300         res = rtw_enqueue_cmd(pcmdpriv, ph2c);
8301
8302
8303 exit:
8304
8305 _func_exit_;
8306
8307         return res;
8308 }
8309
8310 u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
8311 {
8312         u8 evt_code;
8313         u16 evt_sz;
8314         uint    *peventbuf;
8315         void (*event_callback)(struct adapter *dev, u8 *pbuf);
8316         struct evt_priv *pevt_priv = &(padapter->evtpriv);
8317
8318         peventbuf = (uint *)pbuf;
8319         evt_sz = (u16)(*peventbuf&0xffff);
8320         evt_code = (u8)((*peventbuf>>16)&0xff);
8321
8322         /*  checking if event code is valid */
8323         if (evt_code >= MAX_C2HEVT) {
8324                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
8325                 goto _abort_event_;
8326         }
8327
8328         /*  checking if event size match the event parm size */
8329         if ((wlanevents[evt_code].parmsize != 0) &&
8330             (wlanevents[evt_code].parmsize != evt_sz)) {
8331                 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
8332                          ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
8333                          evt_code, wlanevents[evt_code].parmsize, evt_sz));
8334                 goto _abort_event_;
8335         }
8336
8337         ATOMIC_INC(&pevt_priv->event_seq);
8338
8339         peventbuf += 2;
8340
8341         if (peventbuf) {
8342                 event_callback = wlanevents[evt_code].event_callback;
8343                 event_callback(padapter, (u8 *)peventbuf);
8344
8345                 pevt_priv->evt_done_cnt++;
8346         }
8347
8348 _abort_event_:
8349         return H2C_SUCCESS;
8350 }
8351
8352 u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
8353 {
8354         if (!pbuf)
8355                 return H2C_PARAMETERS_ERROR;
8356
8357         return H2C_SUCCESS;
8358 }
8359
8360 u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
8361 {
8362         if (send_beacon(padapter) == _FAIL) {
8363                 DBG_88E("issue_beacon, fail!\n");
8364                 return H2C_PARAMETERS_ERROR;
8365         }
8366 #ifdef CONFIG_88EU_AP_MODE
8367         else { /* tx bc/mc frames after update TIM */
8368                 unsigned long irqL;
8369                 struct sta_info *psta_bmc;
8370                 struct list_head *xmitframe_plist, *xmitframe_phead;
8371                 struct xmit_frame *pxmitframe = NULL;
8372                 struct sta_priv  *pstapriv = &padapter->stapriv;
8373
8374                 /* for BC/MC Frames */
8375                 psta_bmc = rtw_get_bcmc_stainfo(padapter);
8376                 if (!psta_bmc)
8377                         return H2C_SUCCESS;
8378
8379                 if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
8380                         rtw_msleep_os(10);/*  10ms, ATIM(HIQ) Windows */
8381                         _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8382
8383                         xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
8384                         xmitframe_plist = get_next(xmitframe_phead);
8385
8386                         while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
8387                                 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
8388
8389                                 xmitframe_plist = get_next(xmitframe_plist);
8390
8391                                 rtw_list_delete(&pxmitframe->list);
8392
8393                                 psta_bmc->sleepq_len--;
8394                                 if (psta_bmc->sleepq_len > 0)
8395                                         pxmitframe->attrib.mdata = 1;
8396                                 else
8397                                         pxmitframe->attrib.mdata = 0;
8398
8399                                 pxmitframe->attrib.triggered = 1;
8400
8401                                 pxmitframe->attrib.qsel = 0x11;/* HIQ */
8402
8403                                 _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8404                                 if (rtw_hal_xmit(padapter, pxmitframe))
8405                                         rtw_os_xmit_complete(padapter, pxmitframe);
8406                                 _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8407                         }
8408                         _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8409                 }
8410         }
8411 #endif
8412         return H2C_SUCCESS;
8413 }
8414
8415 u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
8416 {
8417         struct set_ch_parm *set_ch_parm;
8418         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8419
8420         if (!pbuf)
8421                 return H2C_PARAMETERS_ERROR;
8422
8423         set_ch_parm = (struct set_ch_parm *)pbuf;
8424
8425         DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
8426                 FUNC_NDEV_ARG(padapter->pnetdev),
8427                 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
8428
8429         pmlmeext->cur_channel = set_ch_parm->ch;
8430         pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
8431         pmlmeext->cur_bwmode = set_ch_parm->bw;
8432
8433         set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
8434
8435         return  H2C_SUCCESS;
8436 }
8437
8438 u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
8439 {
8440         struct SetChannelPlan_param *setChannelPlan_param;
8441         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8442
8443         if (!pbuf)
8444                 return H2C_PARAMETERS_ERROR;
8445
8446         setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
8447
8448         pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
8449         init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
8450
8451         return  H2C_SUCCESS;
8452 }
8453
8454 u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
8455 {
8456         if (!pbuf)
8457                 return H2C_PARAMETERS_ERROR;
8458         return  H2C_SUCCESS;
8459 }
8460
8461 u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
8462 {
8463         return  H2C_REJECTED;
8464 }
8465
8466 /*  TDLS_WRCR           : write RCR DATA BIT */
8467 /*  TDLS_SD_PTI         : issue peer traffic indication */
8468 /*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
8469 /*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
8470 /*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
8471 /*  TDLS_OFF_CH         : first time set channel to off channel */
8472 /*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
8473 /*  TDLS_P_OFF_CH       : periodically go to off channel */
8474 /*  TDLS_P_BASE_CH      : periodically go back to base channel */
8475 /*  TDLS_RS_RCR         : restore RCR */
8476 /*  TDLS_CKALV_PH1      : check alive timer phase1 */
8477 /*  TDLS_CKALV_PH2      : check alive timer phase2 */
8478 /*  TDLS_FREE_STA       : free tdls sta */
8479 u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
8480 {
8481         return H2C_REJECTED;
8482 }