Merge branch 'x86-asmlinkage-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / staging / rtl8188eu / core / rtw_ioctl_set.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_IOCTL_SET_C_
21
22
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <rtw_ioctl_set.h>
26 #include <hal_intf.h>
27
28 #include <usb_osintf.h>
29 #include <usb_ops.h>
30
31 extern void indicate_wx_scan_complete_event(struct adapter *padapter);
32
33 #define IS_MAC_ADDRESS_BROADCAST(addr) \
34 (\
35         ((addr[0] == 0xff) && (addr[1] == 0xff) && \
36                 (addr[2] == 0xff) && (addr[3] == 0xff) && \
37                 (addr[4] == 0xff) && (addr[5] == 0xff))  ? true : false \
38 )
39
40 u8 rtw_validate_ssid(struct ndis_802_11_ssid *ssid)
41 {
42         u8       i;
43         u8      ret = true;
44
45 _func_enter_;
46
47         if (ssid->SsidLength > 32) {
48                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid length >32\n"));
49                 ret = false;
50                 goto exit;
51         }
52
53         for (i = 0; i < ssid->SsidLength; i++) {
54                 /* wifi, printable ascii code must be supported */
55                 if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
56                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid has nonprintabl ascii\n"));
57                         ret = false;
58                         break;
59                 }
60         }
61
62 exit:
63
64 _func_exit_;
65
66         return ret;
67 }
68
69 u8 rtw_do_join(struct adapter *padapter)
70 {
71         struct list_head *plist, *phead;
72         u8 *pibss = NULL;
73         struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
74         struct __queue *queue   = &(pmlmepriv->scanned_queue);
75         u8 ret = _SUCCESS;
76
77 _func_enter_;
78
79         spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
80         phead = get_list_head(queue);
81         plist = get_next(phead);
82
83         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist));
84
85         pmlmepriv->cur_network.join_res = -2;
86
87         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
88
89         pmlmepriv->pscanned = plist;
90
91         pmlmepriv->to_join = true;
92
93         if (_rtw_queue_empty(queue)) {
94                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
95                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
96
97                 /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
98                 /* we try to issue sitesurvey firstly */
99
100                 if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
101                     pmlmepriv->to_roaming > 0) {
102                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_do_join(): site survey if scanned_queue is empty\n."));
103                         /*  submit site_survey_cmd */
104                         ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
105                         if (_SUCCESS != ret) {
106                                 pmlmepriv->to_join = false;
107                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_do_join(): site survey return error\n."));
108                         }
109                 } else {
110                         pmlmepriv->to_join = false;
111                         ret = _FAIL;
112                 }
113
114                 goto exit;
115         } else {
116                 int select_ret;
117
118                 spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
119                 select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
120                 if (select_ret == _SUCCESS) {
121                         pmlmepriv->to_join = false;
122                         _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
123                 } else {
124                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
125                                 /*  submit createbss_cmd to change to a ADHOC_MASTER */
126
127                                 /* pmlmepriv->lock has been acquired by caller... */
128                                 struct wlan_bssid_ex    *pdev_network = &(padapter->registrypriv.dev_network);
129
130                                 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
131
132                                 pibss = padapter->registrypriv.dev_network.MacAddress;
133
134                                 _rtw_memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
135                                 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
136
137                                 rtw_update_registrypriv_dev_network(padapter);
138
139                                 rtw_generate_random_ibss(pibss);
140
141                                 if (rtw_createbss_cmd(padapter) != _SUCCESS) {
142                                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>do_goin: rtw_createbss_cmd status FAIL***\n "));
143                                         ret =  false;
144                                         goto exit;
145                                 }
146                                 pmlmepriv->to_join = false;
147
148                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
149                                          ("***Error => rtw_select_and_join_from_scanned_queue FAIL under STA_Mode***\n "));
150                         } else {
151                                 /*  can't associate ; reset under-linking */
152                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
153
154                                 /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
155                                 /* we try to issue sitesurvey firstly */
156                                 if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
157                                     pmlmepriv->to_roaming > 0) {
158                                         ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
159                                         if (_SUCCESS != ret) {
160                                                 pmlmepriv->to_join = false;
161                                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
162                                         }
163                                 } else {
164                                         ret = _FAIL;
165                                         pmlmepriv->to_join = false;
166                                 }
167                         }
168                 }
169         }
170
171 exit:
172
173 _func_exit_;
174
175         return ret;
176 }
177
178 u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
179 {
180         u8 status = _SUCCESS;
181         u32 cur_time = 0;
182         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
183
184 _func_enter_;
185
186         DBG_88E_LEVEL(_drv_info_, "set bssid:%pM\n", bssid);
187
188         if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
189              bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
190             (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
191              bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
192                 status = _FAIL;
193                 goto exit;
194         }
195
196         spin_lock_bh(&pmlmepriv->lock);
197
198
199         DBG_88E("Set BSSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
200         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
201                 goto handle_tkip_countermeasure;
202         else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
203                 goto release_mlme_lock;
204
205         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
206                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
207
208                 if (_rtw_memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
209                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)
210                                 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
211                 } else {
212                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set BSSID not the same bssid\n"));
213                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid =%pM\n", (bssid)));
214                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("cur_bssid =%pM\n", (pmlmepriv->cur_network.network.MacAddress)));
215
216                         rtw_disassoc_cmd(padapter, 0, true);
217
218                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
219                                 rtw_indicate_disconnect(padapter);
220
221                         rtw_free_assoc_resources(padapter, 1);
222
223                         if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
224                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
225                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
226                         }
227                 }
228         }
229
230 handle_tkip_countermeasure:
231         /* should we add something here...? */
232
233         if (padapter->securitypriv.btkip_countermeasure) {
234                 cur_time = jiffies;
235
236                 if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
237                         padapter->securitypriv.btkip_countermeasure = false;
238                         padapter->securitypriv.btkip_countermeasure_time = 0;
239                 } else {
240                         status = _FAIL;
241                         goto release_mlme_lock;
242                 }
243         }
244
245         memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
246         pmlmepriv->assoc_by_bssid = true;
247
248         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
249                 pmlmepriv->to_join = true;
250         else
251                 status = rtw_do_join(padapter);
252
253 release_mlme_lock:
254         spin_unlock_bh(&pmlmepriv->lock);
255
256 exit:
257         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
258                  ("rtw_set_802_11_bssid: status=%d\n", status));
259
260 _func_exit_;
261
262         return status;
263 }
264
265 u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
266 {
267         u8 status = _SUCCESS;
268         u32 cur_time = 0;
269
270         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
271         struct wlan_network *pnetwork = &pmlmepriv->cur_network;
272
273 _func_enter_;
274
275         DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n",
276                       ssid->Ssid, get_fwstate(pmlmepriv));
277
278         if (!padapter->hw_init_completed) {
279                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
280                          ("set_ssid: hw_init_completed == false =>exit!!!\n"));
281                 status = _FAIL;
282                 goto exit;
283         }
284
285         spin_lock_bh(&pmlmepriv->lock);
286
287         DBG_88E("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
288         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
289                 goto handle_tkip_countermeasure;
290         } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
291                 goto release_mlme_lock;
292         }
293
294         if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
295                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
296                          ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
297
298                 if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
299                     (_rtw_memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength))) {
300                         if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false)) {
301                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
302                                          ("Set SSID is the same ssid, fw_state = 0x%08x\n",
303                                           get_fwstate(pmlmepriv)));
304
305                                 if (!rtw_is_same_ibss(padapter, pnetwork)) {
306                                         /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
307                                         rtw_disassoc_cmd(padapter, 0, true);
308
309                                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
310                                                 rtw_indicate_disconnect(padapter);
311
312                                         rtw_free_assoc_resources(padapter, 1);
313
314                                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
315                                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
316                                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
317                                         }
318                                 } else {
319                                         goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
320                                 }
321                         } else {
322                                 rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
323                         }
324                 } else {
325                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n"));
326                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength));
327                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength));
328
329                         rtw_disassoc_cmd(padapter, 0, true);
330
331                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
332                                 rtw_indicate_disconnect(padapter);
333
334                         rtw_free_assoc_resources(padapter, 1);
335
336                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
337                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
338                                 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
339                         }
340                 }
341         }
342
343 handle_tkip_countermeasure:
344
345         if (padapter->securitypriv.btkip_countermeasure) {
346                 cur_time = jiffies;
347
348                 if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ) {
349                         padapter->securitypriv.btkip_countermeasure = false;
350                         padapter->securitypriv.btkip_countermeasure_time = 0;
351                 } else {
352                         status = _FAIL;
353                         goto release_mlme_lock;
354                 }
355         }
356
357         memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
358         pmlmepriv->assoc_by_bssid = false;
359
360         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
361                 pmlmepriv->to_join = true;
362         } else {
363                 status = rtw_do_join(padapter);
364         }
365
366 release_mlme_lock:
367         spin_unlock_bh(&pmlmepriv->lock);
368
369 exit:
370         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
371                  ("-rtw_set_802_11_ssid: status =%d\n", status));
372 _func_exit_;
373         return status;
374 }
375
376 u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
377         enum ndis_802_11_network_infra networktype)
378 {
379         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
380         struct  wlan_network    *cur_network = &pmlmepriv->cur_network;
381         enum ndis_802_11_network_infra *pold_state = &(cur_network->network.InfrastructureMode);
382
383 _func_enter_;
384
385         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
386                  ("+rtw_set_802_11_infrastructure_mode: old =%d new =%d fw_state = 0x%08x\n",
387                   *pold_state, networktype, get_fwstate(pmlmepriv)));
388
389         if (*pold_state != networktype) {
390                 spin_lock_bh(&pmlmepriv->lock);
391
392                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
393                 /* DBG_88E("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
394
395                 if (*pold_state == Ndis802_11APMode) {
396                         /* change to other mode from Ndis802_11APMode */
397                         cur_network->join_res = -1;
398
399 #ifdef CONFIG_88EU_AP_MODE
400                         stop_ap_mode(padapter);
401 #endif
402                 }
403
404                 if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
405                     (*pold_state == Ndis802_11IBSS))
406                         rtw_disassoc_cmd(padapter, 0, true);
407
408                 if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
409                     (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
410                         rtw_free_assoc_resources(padapter, 1);
411
412                 if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
413                         if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
414                                 rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not */
415                }
416
417                 *pold_state = networktype;
418
419                 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
420
421                 switch (networktype) {
422                 case Ndis802_11IBSS:
423                         set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
424                         break;
425                 case Ndis802_11Infrastructure:
426                         set_fwstate(pmlmepriv, WIFI_STATION_STATE);
427                         break;
428                 case Ndis802_11APMode:
429                         set_fwstate(pmlmepriv, WIFI_AP_STATE);
430 #ifdef CONFIG_88EU_AP_MODE
431                         start_ap_mode(padapter);
432 #endif
433                         break;
434                 case Ndis802_11AutoUnknown:
435                 case Ndis802_11InfrastructureMax:
436                         break;
437                 }
438                 spin_unlock_bh(&pmlmepriv->lock);
439         }
440
441 _func_exit_;
442
443         return true;
444 }
445
446
447 u8 rtw_set_802_11_disassociate(struct adapter *padapter)
448 {
449         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
450
451 _func_enter_;
452
453         spin_lock_bh(&pmlmepriv->lock);
454
455         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
456                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
457                          ("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n"));
458
459                 rtw_disassoc_cmd(padapter, 0, true);
460                 rtw_indicate_disconnect(padapter);
461                 rtw_free_assoc_resources(padapter, 1);
462                 rtw_pwr_wakeup(padapter);
463         }
464
465         spin_unlock_bh(&pmlmepriv->lock);
466
467 _func_exit_;
468
469         return true;
470 }
471
472 u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
473 {
474         struct  mlme_priv               *pmlmepriv = &padapter->mlmepriv;
475         u8      res = true;
476
477 _func_enter_;
478
479         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+rtw_set_802_11_bssid_list_scan(), fw_state =%x\n", get_fwstate(pmlmepriv)));
480
481         if (padapter == NULL) {
482                 res = false;
483                 goto exit;
484         }
485         if (!padapter->hw_init_completed) {
486                 res = false;
487                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n === rtw_set_802_11_bssid_list_scan:hw_init_completed == false ===\n"));
488                 goto exit;
489         }
490
491         if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) ||
492             (pmlmepriv->LinkDetectInfo.bBusyTraffic)) {
493                 /*  Scan or linking is in progress, do nothing. */
494                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_set_802_11_bssid_list_scan fail since fw_state = %x\n", get_fwstate(pmlmepriv)));
495                 res = true;
496
497                 if (check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)) == true) {
498                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n\n"));
499                 } else {
500                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###pmlmepriv->sitesurveyctrl.traffic_busy == true\n\n"));
501                 }
502         } else {
503                 if (rtw_is_scan_deny(padapter)) {
504                         DBG_88E(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
505                         indicate_wx_scan_complete_event(padapter);
506                         return _SUCCESS;
507                 }
508
509                 spin_lock_bh(&pmlmepriv->lock);
510
511                 res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
512
513                 spin_unlock_bh(&pmlmepriv->lock);
514         }
515 exit:
516
517 _func_exit_;
518
519         return res;
520 }
521
522 u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
523 {
524         struct security_priv *psecuritypriv = &padapter->securitypriv;
525         int res;
526         u8 ret;
527
528 _func_enter_;
529
530         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_802_11_auth.mode(): mode =%x\n", authmode));
531
532         psecuritypriv->ndisauthtype = authmode;
533
534         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
535                  ("rtw_set_802_11_authentication_mode:psecuritypriv->ndisauthtype=%d",
536                  psecuritypriv->ndisauthtype));
537
538         if (psecuritypriv->ndisauthtype > 3)
539                 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
540
541         res = rtw_set_auth(padapter, psecuritypriv);
542
543         if (res == _SUCCESS)
544                 ret = true;
545         else
546                 ret = false;
547
548 _func_exit_;
549
550         return ret;
551 }
552
553 u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
554 {
555         int             keyid, res;
556         struct security_priv *psecuritypriv = &(padapter->securitypriv);
557         u8              ret = _SUCCESS;
558
559 _func_enter_;
560
561         keyid = wep->KeyIndex & 0x3fffffff;
562
563         if (keyid >= 4) {
564                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MgntActrtw_set_802_11_add_wep:keyid>4 =>fail\n"));
565                 ret = false;
566                 goto exit;
567         }
568
569         switch (wep->KeyLength) {
570         case 5:
571                 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
572                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 5\n"));
573                 break;
574         case 13:
575                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
576                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 13\n"));
577                 break;
578         default:
579                 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
580                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength!= 5 or 13\n"));
581                 break;
582         }
583         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
584                  ("rtw_set_802_11_add_wep:befor memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x  keyid =%x\n",
585                  wep->KeyLength, wep->KeyIndex, keyid));
586
587         memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
588
589         psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
590
591         psecuritypriv->dot11PrivacyKeyIndex = keyid;
592
593         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
594                  ("rtw_set_802_11_add_wep:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
595                  psecuritypriv->dot11DefKey[keyid].skey[0],
596                  psecuritypriv->dot11DefKey[keyid].skey[1],
597                  psecuritypriv->dot11DefKey[keyid].skey[2],
598                  psecuritypriv->dot11DefKey[keyid].skey[3],
599                  psecuritypriv->dot11DefKey[keyid].skey[4],
600                  psecuritypriv->dot11DefKey[keyid].skey[5],
601                  psecuritypriv->dot11DefKey[keyid].skey[6],
602                  psecuritypriv->dot11DefKey[keyid].skey[7],
603                  psecuritypriv->dot11DefKey[keyid].skey[8],
604                  psecuritypriv->dot11DefKey[keyid].skey[9],
605                  psecuritypriv->dot11DefKey[keyid].skey[10],
606                  psecuritypriv->dot11DefKey[keyid].skey[11],
607                  psecuritypriv->dot11DefKey[keyid].skey[12]));
608
609         res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
610
611         if (res == _FAIL)
612                 ret = false;
613 exit:
614 _func_exit_;
615         return ret;
616 }
617
618 u8 rtw_set_802_11_remove_wep(struct adapter *padapter, u32 keyindex)
619 {
620         u8 ret = _SUCCESS;
621
622 _func_enter_;
623         if (keyindex >= 0x80000000 || padapter == NULL) {
624                 ret = false;
625                 goto exit;
626         } else {
627                 int res;
628                 struct security_priv *psecuritypriv = &(padapter->securitypriv);
629                 if (keyindex < 4) {
630                         _rtw_memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16);
631                         res = rtw_set_key(padapter, psecuritypriv, keyindex, 0);
632                         psecuritypriv->dot11DefKeylen[keyindex] = 0;
633                         if (res == _FAIL)
634                                 ret = _FAIL;
635                 } else {
636                         ret = _FAIL;
637                 }
638         }
639 exit:
640
641 _func_exit_;
642         return ret;
643 }
644
645 u8 rtw_set_802_11_add_key(struct adapter *padapter, struct ndis_802_11_key *key)
646 {
647         uint    encryptionalgo;
648         u8 *pbssid;
649         struct sta_info *stainfo;
650         u8      bgroup = false;
651         u8      bgrouptkey = false;/* can be removed later */
652         u8      ret = _SUCCESS;
653
654 _func_enter_;
655
656         if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)) {
657                 /*  It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination, */
658                 /*  it must fail the request and return NDIS_STATUS_INVALID_DATA. */
659                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
660                          ("rtw_set_802_11_add_key: ((key->KeyIndex & 0x80000000)==0)[=%d]",
661                          (int)(key->KeyIndex & 0x80000000) == 0));
662                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
663                          ("rtw_set_802_11_add_key:((key->KeyIndex & 0x40000000)>0)[=%d]",
664                          (int)(key->KeyIndex & 0x40000000) > 0));
665                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
666                          ("rtw_set_802_11_add_key: key->KeyIndex=%d\n",
667                          (int)key->KeyIndex));
668                 ret = _FAIL;
669                 goto exit;
670         }
671
672         if (key->KeyIndex & 0x40000000) {
673                 /*  Pairwise key */
674
675                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ Pairwise key +++++\n"));
676
677                 pbssid = get_bssid(&padapter->mlmepriv);
678                 stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
679
680                 if ((stainfo != NULL) && (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)) {
681                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
682                                  ("OID_802_11_ADD_KEY:(stainfo!=NULL)&&(Adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\n"));
683                         encryptionalgo = stainfo->dot118021XPrivacy;
684                 } else {
685                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: stainfo == NULL)||(Adapter->securitypriv.dot11AuthAlgrthm!= dot11AuthAlgrthm_8021X)\n"));
686                         encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
687                 }
688
689                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
690                          ("rtw_set_802_11_add_key: (encryptionalgo==%d)!\n",
691                          encryptionalgo));
692                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
693                          ("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11PrivacyAlgrthm==%d)!\n",
694                          padapter->securitypriv.dot11PrivacyAlgrthm));
695                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
696                          ("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11AuthAlgrthm==%d)!\n",
697                          padapter->securitypriv.dot11AuthAlgrthm));
698
699                 if ((stainfo != NULL))
700                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
701                                  ("rtw_set_802_11_add_key: (stainfo->dot118021XPrivacy==%d)!\n",
702                                  stainfo->dot118021XPrivacy));
703
704                 if (key->KeyIndex & 0x000000FF) {
705                         /*  The key index is specified in the lower 8 bits by values of zero to 255. */
706                         /*  The key index should be set to zero for a Pairwise key, and the driver should fail with */
707                         /*  NDIS_STATUS_INVALID_DATA if the lower 8 bits is not zero */
708                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, (" key->KeyIndex & 0x000000FF.\n"));
709                         ret = _FAIL;
710                         goto exit;
711                 }
712
713                 /*  check BSSID */
714                 if (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == true) {
715                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MacAddr_isBcst(key->BSSID)\n"));
716                         ret = false;
717                         goto exit;
718                 }
719
720                 /*  Check key length for TKIP. */
721                 if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
722                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("TKIP KeyLength:0x%x != 32\n", key->KeyLength));
723                         ret = _FAIL;
724                         goto exit;
725                 }
726
727                 /*  Check key length for AES. */
728                 if ((encryptionalgo == _AES_) && (key->KeyLength != 16)) {
729                         /*  For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case. */
730                         if (key->KeyLength == 32) {
731                                 key->KeyLength = 16;
732                         } else {
733                                 ret = _FAIL;
734                                 goto exit;
735                         }
736                 }
737
738                 /*  Check key length for WEP. For NDTEST, 2005.01.27, by rcnjko. */
739                 if ((encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_) &&
740                     (key->KeyLength != 5 && key->KeyLength != 13)) {
741                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("WEP KeyLength:0x%x != 5 or 13\n", key->KeyLength));
742                         ret = _FAIL;
743                         goto exit;
744                 }
745
746                 bgroup = false;
747
748                 /*  Check the pairwise key. Added by Annie, 2005-07-06. */
749                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
750                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("[Pairwise Key set]\n"));
751                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
752                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key index: 0x%8x(0x%8x)\n", key->KeyIndex, (key->KeyIndex&0x3)));
753                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key Length: %d\n", key->KeyLength));
754                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
755
756         } else {
757                 /*  Group key - KeyIndex(BIT30 == 0) */
758                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ Group key +++++\n"));
759
760
761                 /*  when add wep key through add key and didn't assigned encryption type before */
762                 if ((padapter->securitypriv.ndisauthtype <= 3) &&
763                     (padapter->securitypriv.dot118021XGrpPrivacy == 0)) {
764                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
765                                  ("keylen =%d(Adapter->securitypriv.dot11PrivacyAlgrthm=%x )padapter->securitypriv.dot118021XGrpPrivacy(%x)\n",
766                                  key->KeyLength, padapter->securitypriv.dot11PrivacyAlgrthm,
767                                  padapter->securitypriv.dot118021XGrpPrivacy));
768                         switch (key->KeyLength) {
769                         case 5:
770                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
771                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
772                                          ("Adapter->securitypriv.dot11PrivacyAlgrthm=%x key->KeyLength=%u\n",
773                                          padapter->securitypriv.dot11PrivacyAlgrthm, key->KeyLength));
774                                 break;
775                         case 13:
776                                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
777                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
778                                          ("Adapter->securitypriv.dot11PrivacyAlgrthm=%x key->KeyLength=%u\n",
779                                          padapter->securitypriv.dot11PrivacyAlgrthm, key->KeyLength));
780                                 break;
781                         default:
782                                 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
783                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
784                                          ("Adapter->securitypriv.dot11PrivacyAlgrthm=%x key->KeyLength=%u\n",
785                                          padapter->securitypriv.dot11PrivacyAlgrthm, key->KeyLength));
786                                 break;
787                         }
788
789                         encryptionalgo = padapter->securitypriv.dot11PrivacyAlgrthm;
790
791                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
792                                  (" Adapter->securitypriv.dot11PrivacyAlgrthm=%x\n",
793                                  padapter->securitypriv.dot11PrivacyAlgrthm));
794
795                 } else {
796                         encryptionalgo = padapter->securitypriv.dot118021XGrpPrivacy;
797                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
798                                  ("(Adapter->securitypriv.dot11PrivacyAlgrthm=%x)encryptionalgo(%x)=padapter->securitypriv.dot118021XGrpPrivacy(%x)keylen=%d\n",
799                                  padapter->securitypriv.dot11PrivacyAlgrthm, encryptionalgo,
800                                  padapter->securitypriv.dot118021XGrpPrivacy, key->KeyLength));
801                 }
802
803                 if ((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE) == true) && (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == false)) {
804                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
805                                  (" IBSS but BSSID is not Broadcast Address.\n"));
806                         ret = _FAIL;
807                         goto exit;
808                 }
809
810                 /*  Check key length for TKIP */
811                 if ((encryptionalgo == _TKIP_) && (key->KeyLength != 32)) {
812                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
813                                  (" TKIP GTK KeyLength:%u != 32\n", key->KeyLength));
814                         ret = _FAIL;
815                         goto exit;
816                 } else if (encryptionalgo == _AES_ && (key->KeyLength != 16 && key->KeyLength != 32)) {
817                         /*  Check key length for AES */
818                         /*  For NDTEST, we allow keylen = 32 in this case. 2005.01.27, by rcnjko. */
819                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
820                                  ("<=== SetInfo, OID_802_11_ADD_KEY: AES GTK KeyLength:%u != 16 or 32\n",
821                                  key->KeyLength));
822                         ret = _FAIL;
823                         goto exit;
824                 }
825
826                 /*  Change the key length for EAPPkt9x.vxd. Added by Annie, 2005-11-03. */
827                 if ((encryptionalgo ==  _AES_) && (key->KeyLength == 32)) {
828                         key->KeyLength = 16;
829                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("AES key length changed: %u\n", key->KeyLength));
830                 }
831
832                 if (key->KeyIndex & 0x8000000) {/* error ??? 0x8000_0000 */
833                         bgrouptkey = true;
834                 }
835
836                 if ((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)) &&
837                     (check_fwstate(&padapter->mlmepriv, _FW_LINKED)))
838                         bgrouptkey = true;
839                 bgroup = true;
840                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
841                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("[Group Key set]\n"));
842                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n")) ;
843                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key index: 0x%8x(0x%8x)\n", key->KeyIndex, (key->KeyIndex&0x3)));
844                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("key Length: %d\n", key->KeyLength)) ;
845                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("------------------------------------------\n"));
846         }
847
848         /*  If WEP encryption algorithm, just call rtw_set_802_11_add_wep(). */
849         if ((padapter->securitypriv.dot11AuthAlgrthm != dot11AuthAlgrthm_8021X) &&
850             (encryptionalgo == _WEP40_ || encryptionalgo == _WEP104_)) {
851                 u32 keyindex;
852                 u32 len = FIELD_OFFSET(struct ndis_802_11_key, KeyMaterial) + key->KeyLength;
853                 struct ndis_802_11_wep *wep = &padapter->securitypriv.ndiswep;
854
855                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ WEP key +++++\n"));
856
857                 wep->Length = len;
858                 keyindex = key->KeyIndex&0x7fffffff;
859                 wep->KeyIndex = keyindex ;
860                 wep->KeyLength = key->KeyLength;
861
862                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY:Before memcpy\n"));
863
864                 memcpy(wep->KeyMaterial, key->KeyMaterial, key->KeyLength);
865                 memcpy(&(padapter->securitypriv.dot11DefKey[keyindex].skey[0]), key->KeyMaterial, key->KeyLength);
866
867                 padapter->securitypriv.dot11DefKeylen[keyindex] = key->KeyLength;
868                 padapter->securitypriv.dot11PrivacyKeyIndex = keyindex;
869
870                 ret = rtw_set_802_11_add_wep(padapter, wep);
871                 goto exit;
872         }
873         if (key->KeyIndex & 0x20000000) {
874                 /*  SetRSC */
875                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("OID_802_11_ADD_KEY: +++++ SetRSC+++++\n"));
876                 if (bgroup) {
877                         unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
878                         memcpy(&padapter->securitypriv.dot11Grprxpn, &keysrc, 8);
879                 } else {
880                         unsigned long long keysrc = key->KeyRSC & 0x00FFFFFFFFFFFFULL;
881                         memcpy(&padapter->securitypriv.dot11Grptxpn, &keysrc, 8);
882                 }
883         }
884
885         /*  Indicate this key idx is used for TX */
886         /*  Save the key in KeyMaterial */
887         if (bgroup) { /*  Group transmit key */
888                 int res;
889
890                 if (bgrouptkey)
891                         padapter->securitypriv.dot118021XGrpKeyid = (u8)key->KeyIndex;
892                 if ((key->KeyIndex&0x3) == 0) {
893                         ret = _FAIL;
894                         goto exit;
895                 }
896                 _rtw_memset(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
897                 _rtw_memset(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
898                 _rtw_memset(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
899
900                 if ((key->KeyIndex & 0x10000000)) {
901                         memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
902                         memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
903
904                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
905                                  ("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
906                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],
907                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
908                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],
909                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
910                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],
911                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
912                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],
913                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
914                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
915                 } else {
916                         memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
917                         memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
918
919                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
920                                  ("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
921                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],
922                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
923                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],
924                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
925                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],
926                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
927                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],
928                                  padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
929                         RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
930                                  ("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
931                 }
932
933                 /* set group key by index */
934                 memcpy(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial, key->KeyLength);
935
936                 key->KeyIndex = key->KeyIndex & 0x03;
937
938                 padapter->securitypriv.binstallGrpkey = true;
939
940                 padapter->securitypriv.bcheck_grpkey = false;
941
942                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("reset group key"));
943
944                 res = rtw_set_key(padapter, &padapter->securitypriv, key->KeyIndex, 1);
945
946                 if (res == _FAIL)
947                         ret = _FAIL;
948
949                 goto exit;
950
951         } else { /*  Pairwise Key */
952                 u8 res;
953
954                 pbssid = get_bssid(&padapter->mlmepriv);
955                 stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
956
957                 if (stainfo != NULL) {
958                         _rtw_memset(&stainfo->dot118021x_UncstKey, 0, 16);/*  clear keybuffer */
959
960                         memcpy(&stainfo->dot118021x_UncstKey, key->KeyMaterial, 16);
961
962                         if (encryptionalgo == _TKIP_) {
963                                 padapter->securitypriv.busetkipkey = false;
964
965                                 /* _set_timer(&padapter->securitypriv.tkip_timer, 50); */
966
967                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n========== _set_timer\n"));
968
969                                 /*  if TKIP, save the Receive/Transmit MIC key in KeyMaterial[128-255] */
970                                 if ((key->KeyIndex & 0x10000000)) {
971                                         memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 16, 8);
972                                         memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 24, 8);
973
974                                 } else {
975                                         memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 24, 8);
976                                         memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 16, 8);
977                                 }
978                         }
979
980
981                         /* Set key to CAM through H2C command */
982                         if (bgrouptkey) { /* never go to here */
983                                 res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, false);
984                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(group)\n"));
985                         } else {
986                                 res = rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, true);
987                                 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(unicast)\n"));
988                         }
989                         if (!res)
990                                 ret = _FAIL;
991                 }
992         }
993 exit:
994
995 _func_exit_;
996         return ret;
997 }
998
999 u8 rtw_set_802_11_remove_key(struct adapter *padapter, struct ndis_802_11_remove_key *key)
1000 {
1001         u8 *pbssid;
1002         struct sta_info *stainfo;
1003         u8      bgroup = (key->KeyIndex & 0x4000000) > 0 ? false : true;
1004         u8      keyIndex = (u8)key->KeyIndex & 0x03;
1005         u8      ret = _SUCCESS;
1006
1007 _func_enter_;
1008
1009         if ((key->KeyIndex & 0xbffffffc) > 0) {
1010                 ret = _FAIL;
1011                 goto exit;
1012         }
1013
1014         if (bgroup) {
1015                 /*  clear group key by index */
1016
1017                 _rtw_memset(&padapter->securitypriv.dot118021XGrpKey[keyIndex], 0, 16);
1018
1019                 /*  \todo Send a H2C Command to Firmware for removing this Key in CAM Entry. */
1020         } else {
1021                 pbssid = get_bssid(&padapter->mlmepriv);
1022                 stainfo = rtw_get_stainfo(&padapter->stapriv, pbssid);
1023                 if (stainfo) {
1024                         /*  clear key by BSSID */
1025                         _rtw_memset(&stainfo->dot118021x_UncstKey, 0, 16);
1026
1027                         /*  \todo Send a H2C Command to Firmware for disable this Key in CAM Entry. */
1028                 } else {
1029                         ret = _FAIL;
1030                         goto exit;
1031                 }
1032         }
1033 exit:
1034
1035 _func_exit_;
1036         return ret;
1037 }
1038
1039 /*
1040 * rtw_get_cur_max_rate -
1041 * @adapter: pointer to struct adapter structure
1042 *
1043 * Return 0 or 100Kbps
1044 */
1045 u16 rtw_get_cur_max_rate(struct adapter *adapter)
1046 {
1047         int     i = 0;
1048         u8      *p;
1049         u16     rate = 0, max_rate = 0;
1050         struct mlme_ext_priv    *pmlmeext = &adapter->mlmeextpriv;
1051         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1052         struct registry_priv *pregistrypriv = &adapter->registrypriv;
1053         struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
1054         struct wlan_bssid_ex  *pcur_bss = &pmlmepriv->cur_network.network;
1055         struct rtw_ieee80211_ht_cap *pht_capie;
1056         u8      rf_type = 0;
1057         u8      bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
1058         u16     mcs_rate = 0;
1059         u32     ht_ielen = 0;
1060
1061         if (adapter->registrypriv.mp_mode == 1) {
1062                 if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
1063                         return 0;
1064         }
1065
1066         if ((!check_fwstate(pmlmepriv, _FW_LINKED)) &&
1067             (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
1068                 return 0;
1069
1070         if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) {
1071                 p = rtw_get_ie(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->IELength-12);
1072                 if (p && ht_ielen > 0) {
1073                         pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
1074
1075                         memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2);
1076
1077                         /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
1078                         bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
1079
1080                         short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
1081                         short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
1082
1083                         rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
1084                         max_rate = rtw_mcs_rate(
1085                                 rf_type,
1086                                 bw_40MHz & (pregistrypriv->cbw40_enable),
1087                                 short_GI_20,
1088                                 short_GI_40,
1089                                 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
1090                         );
1091                 }
1092         } else {
1093                 while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
1094                         rate = pcur_bss->SupportedRates[i]&0x7F;
1095                         if (rate > max_rate)
1096                                 max_rate = rate;
1097                         i++;
1098                 }
1099
1100                 max_rate = max_rate*10/2;
1101         }
1102
1103         return max_rate;
1104 }
1105
1106 /*
1107 * rtw_set_scan_mode -
1108 * @adapter: pointer to struct adapter structure
1109 * @scan_mode:
1110 *
1111 * Return _SUCCESS or _FAIL
1112 */
1113 int rtw_set_scan_mode(struct adapter *adapter, enum rt_scan_type scan_mode)
1114 {
1115         if (scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
1116                 return _FAIL;
1117
1118         adapter->mlmepriv.scan_mode = scan_mode;
1119
1120         return _SUCCESS;
1121 }
1122
1123 /*
1124 * rtw_set_channel_plan -
1125 * @adapter: pointer to struct adapter structure
1126 * @channel_plan:
1127 *
1128 * Return _SUCCESS or _FAIL
1129 */
1130 int rtw_set_channel_plan(struct adapter *adapter, u8 channel_plan)
1131 {
1132         /* handle by cmd_thread to sync with scan operation */
1133         return rtw_set_chplan_cmd(adapter, channel_plan, 1);
1134 }
1135
1136 /*
1137 * rtw_set_country -
1138 * @adapter: pointer to struct adapter structure
1139 * @country_code: string of country code
1140 *
1141 * Return _SUCCESS or _FAIL
1142 */
1143 int rtw_set_country(struct adapter *adapter, const char *country_code)
1144 {
1145         int channel_plan = RT_CHANNEL_DOMAIN_WORLD_WIDE_5G;
1146
1147         DBG_88E("%s country_code:%s\n", __func__, country_code);
1148
1149         /* TODO: should have a table to match country code and RT_CHANNEL_DOMAIN */
1150         /* TODO: should consider 2-character and 3-character country code */
1151         if (0 == strcmp(country_code, "US"))
1152                 channel_plan = RT_CHANNEL_DOMAIN_FCC;
1153         else if (0 == strcmp(country_code, "EU"))
1154                 channel_plan = RT_CHANNEL_DOMAIN_ETSI;
1155         else if (0 == strcmp(country_code, "JP"))
1156                 channel_plan = RT_CHANNEL_DOMAIN_MKK;
1157         else if (0 == strcmp(country_code, "CN"))
1158                 channel_plan = RT_CHANNEL_DOMAIN_CHINA;
1159         else
1160                 DBG_88E("%s unknown country_code:%s\n", __func__, country_code);
1161
1162         return rtw_set_channel_plan(adapter, channel_plan);
1163 }