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