GNU Linux-libre 4.9.337-gnu1
[releases.git] / drivers / staging / rtl8712 / rtl871x_mlme.c
1 /******************************************************************************
2  * rtl871x_mlme.c
3  *
4  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5  * Linux device driver for RTL8192SU
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of version 2 of the GNU General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * Modifications for inclusion into the Linux staging tree are
21  * Copyright(c) 2010 Larry Finger. All rights reserved.
22  *
23  * Contact information:
24  * WLAN FAE <wlanfae@realtek.com>
25  * Larry Finger <Larry.Finger@lwfinger.net>
26  *
27  ******************************************************************************/
28
29 #define _RTL871X_MLME_C_
30
31 #include <linux/etherdevice.h>
32
33 #include "osdep_service.h"
34 #include "drv_types.h"
35 #include "recv_osdep.h"
36 #include "xmit_osdep.h"
37 #include "mlme_osdep.h"
38 #include "sta_info.h"
39 #include "wifi.h"
40 #include "wlan_bssdef.h"
41
42 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
43
44 static sint _init_mlme_priv(struct _adapter *padapter)
45 {
46         sint    i;
47         u8      *pbuf;
48         struct wlan_network     *pnetwork;
49         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
50
51         memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
52         pmlmepriv->nic_hdl = (u8 *)padapter;
53         pmlmepriv->pscanned = NULL;
54         pmlmepriv->fw_state = 0;
55         pmlmepriv->cur_network.network.InfrastructureMode =
56                                  Ndis802_11AutoUnknown;
57         /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
58         pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
59         spin_lock_init(&(pmlmepriv->lock));
60         spin_lock_init(&(pmlmepriv->lock2));
61         _init_queue(&(pmlmepriv->free_bss_pool));
62         _init_queue(&(pmlmepriv->scanned_queue));
63         set_scanned_network_val(pmlmepriv, 0);
64         memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
65         pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
66                              GFP_ATOMIC);
67         if (!pbuf)
68                 return _FAIL;
69         pmlmepriv->free_bss_buf = pbuf;
70         pnetwork = (struct wlan_network *)pbuf;
71         for (i = 0; i < MAX_BSS_CNT; i++) {
72                 INIT_LIST_HEAD(&(pnetwork->list));
73                 list_add_tail(&(pnetwork->list),
74                                  &(pmlmepriv->free_bss_pool.queue));
75                 pnetwork++;
76         }
77         pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
78         pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
79         pmlmepriv->sitesurveyctrl.traffic_busy = false;
80         /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
81         r8712_init_mlme_timer(padapter);
82         return _SUCCESS;
83 }
84
85 struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
86 {
87         unsigned long irqL;
88         struct wlan_network *pnetwork;
89         struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
90
91         spin_lock_irqsave(&free_queue->lock, irqL);
92         pnetwork = list_first_entry_or_null(&free_queue->queue,
93                                             struct wlan_network, list);
94         if (pnetwork) {
95                 list_del_init(&pnetwork->list);
96                 pnetwork->last_scanned = jiffies;
97                 pmlmepriv->num_of_scanned++;
98         }
99         spin_unlock_irqrestore(&free_queue->lock, irqL);
100         return pnetwork;
101 }
102
103 static void _free_network(struct mlme_priv *pmlmepriv,
104                           struct wlan_network *pnetwork)
105 {
106         u32 curr_time, delta_time;
107         unsigned long irqL;
108         struct  __queue *free_queue = &(pmlmepriv->free_bss_pool);
109
110         if (pnetwork == NULL)
111                 return;
112         if (pnetwork->fixed)
113                 return;
114         curr_time = jiffies;
115         delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
116         if (delta_time < SCANQUEUE_LIFETIME)
117                 return;
118         spin_lock_irqsave(&free_queue->lock, irqL);
119         list_del_init(&pnetwork->list);
120         list_add_tail(&pnetwork->list, &free_queue->queue);
121         pmlmepriv->num_of_scanned--;
122         spin_unlock_irqrestore(&free_queue->lock, irqL);
123 }
124
125 static void free_network_nolock(struct mlme_priv *pmlmepriv,
126                           struct wlan_network *pnetwork)
127 {
128         struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
129
130         if (pnetwork == NULL)
131                 return;
132         if (pnetwork->fixed)
133                 return;
134         list_del_init(&pnetwork->list);
135         list_add_tail(&pnetwork->list, &free_queue->queue);
136         pmlmepriv->num_of_scanned--;
137 }
138
139
140 /*
141         return the wlan_network with the matching addr
142         Shall be called under atomic context...
143         to avoid possible racing condition...
144 */
145 static struct wlan_network *_r8712_find_network(struct  __queue *scanned_queue,
146                                          u8 *addr)
147 {
148         unsigned long irqL;
149         struct list_head *phead, *plist;
150         struct wlan_network *pnetwork = NULL;
151
152         if (is_zero_ether_addr(addr))
153                 return NULL;
154         spin_lock_irqsave(&scanned_queue->lock, irqL);
155         phead = &scanned_queue->queue;
156         plist = phead->next;
157         while (plist != phead) {
158                 pnetwork = container_of(plist, struct wlan_network, list);
159                 plist = plist->next;
160                 if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
161                         break;
162         }
163         spin_unlock_irqrestore(&scanned_queue->lock, irqL);
164         return pnetwork;
165 }
166
167 static void _free_network_queue(struct _adapter *padapter)
168 {
169         unsigned long irqL;
170         struct list_head *phead, *plist;
171         struct wlan_network *pnetwork;
172         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
173         struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
174
175         spin_lock_irqsave(&scanned_queue->lock, irqL);
176         phead = &scanned_queue->queue;
177         plist = phead->next;
178         while (!end_of_queue_search(phead, plist)) {
179                 pnetwork = container_of(plist, struct wlan_network, list);
180                 plist = plist->next;
181                 _free_network(pmlmepriv, pnetwork);
182         }
183         spin_unlock_irqrestore(&scanned_queue->lock, irqL);
184 }
185
186 sint r8712_if_up(struct _adapter *padapter)
187 {
188         sint res;
189
190         if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
191             !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
192                 res = false;
193         } else {
194                 res = true;
195         }
196         return res;
197 }
198
199 void r8712_generate_random_ibss(u8 *pibss)
200 {
201         u32 curtime = jiffies;
202
203         pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
204         pibss[1] = 0x11;
205         pibss[2] = 0x87;
206         pibss[3] = (u8)(curtime & 0xff);
207         pibss[4] = (u8)((curtime >> 8) & 0xff);
208         pibss[5] = (u8)((curtime >> 16) & 0xff);
209 }
210
211 uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
212 {
213         return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
214 }
215
216 u8 *r8712_get_capability_from_ie(u8 *ie)
217 {
218         return ie + 8 + 2;
219 }
220
221 int r8712_init_mlme_priv(struct _adapter *padapter)
222 {
223         return _init_mlme_priv(padapter);
224 }
225
226 void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
227 {
228         kfree(pmlmepriv->free_bss_buf);
229 }
230
231 static struct   wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
232 {
233         return _r8712_alloc_network(pmlmepriv);
234 }
235
236 void r8712_free_network_queue(struct _adapter *dev)
237 {
238         _free_network_queue(dev);
239 }
240
241 /*
242         return the wlan_network with the matching addr
243
244         Shall be called under atomic context...
245         to avoid possible racing condition...
246 */
247 static struct wlan_network *r8712_find_network(struct  __queue *scanned_queue,
248                                                u8 *addr)
249 {
250         struct wlan_network *pnetwork = _r8712_find_network(scanned_queue,
251                                                             addr);
252
253         return pnetwork;
254 }
255
256 int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
257 {
258         int ret = true;
259         struct security_priv *psecuritypriv = &adapter->securitypriv;
260
261         if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
262                     (pnetwork->network.Privacy == 0))
263                 ret = false;
264         else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
265                  (pnetwork->network.Privacy == 1))
266                 ret = false;
267         else
268                 ret = true;
269         return ret;
270
271 }
272
273 static int is_same_network(struct wlan_bssid_ex *src,
274                            struct wlan_bssid_ex *dst)
275 {
276          u16 s_cap, d_cap;
277
278         memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
279         memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
280         return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
281                         (src->Configuration.DSConfig ==
282                         dst->Configuration.DSConfig) &&
283                         ((!memcmp(src->MacAddress, dst->MacAddress,
284                         ETH_ALEN))) &&
285                         ((!memcmp(src->Ssid.Ssid,
286                           dst->Ssid.Ssid,
287                           src->Ssid.SsidLength))) &&
288                         ((s_cap & WLAN_CAPABILITY_IBSS) ==
289                         (d_cap & WLAN_CAPABILITY_IBSS)) &&
290                         ((s_cap & WLAN_CAPABILITY_BSS) ==
291                         (d_cap & WLAN_CAPABILITY_BSS));
292
293 }
294
295 struct  wlan_network *r8712_get_oldest_wlan_network(
296                                 struct  __queue *scanned_queue)
297 {
298         struct list_head *plist, *phead;
299         struct  wlan_network    *pwlan = NULL;
300         struct  wlan_network    *oldest = NULL;
301
302         phead = &scanned_queue->queue;
303         plist = phead->next;
304         while (1) {
305                 if (end_of_queue_search(phead, plist) ==  true)
306                         break;
307                 pwlan = container_of(plist, struct wlan_network, list);
308                 if (pwlan->fixed != true) {
309                         if (oldest == NULL ||
310                             time_after((unsigned long)oldest->last_scanned,
311                             (unsigned long)pwlan->last_scanned))
312                                 oldest = pwlan;
313                 }
314                 plist = plist->next;
315         }
316         return oldest;
317 }
318
319 static void update_network(struct wlan_bssid_ex *dst,
320                            struct wlan_bssid_ex *src,
321                            struct _adapter *padapter)
322 {
323         u32 last_evm = 0, tmpVal;
324
325         if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
326             is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
327                 if (padapter->recvpriv.signal_qual_data.total_num++ >=
328                     PHY_LINKQUALITY_SLID_WIN_MAX) {
329                         padapter->recvpriv.signal_qual_data.total_num =
330                                    PHY_LINKQUALITY_SLID_WIN_MAX;
331                         last_evm = padapter->recvpriv.signal_qual_data.
332                                    elements[padapter->recvpriv.
333                                    signal_qual_data.index];
334                         padapter->recvpriv.signal_qual_data.total_val -=
335                                  last_evm;
336                 }
337                 padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
338
339                 padapter->recvpriv.signal_qual_data.
340                           elements[padapter->recvpriv.signal_qual_data.
341                           index++] = src->Rssi;
342                 if (padapter->recvpriv.signal_qual_data.index >=
343                     PHY_LINKQUALITY_SLID_WIN_MAX)
344                         padapter->recvpriv.signal_qual_data.index = 0;
345                 /* <1> Showed on UI for user, in percentage. */
346                 tmpVal = padapter->recvpriv.signal_qual_data.total_val /
347                          padapter->recvpriv.signal_qual_data.total_num;
348                 padapter->recvpriv.signal = (u8)tmpVal;
349
350                 src->Rssi = padapter->recvpriv.signal;
351         } else {
352                 src->Rssi = (src->Rssi + dst->Rssi) / 2;
353         }
354         memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
355 }
356
357 static void update_current_network(struct _adapter *adapter,
358                                    struct wlan_bssid_ex *pnetwork)
359 {
360         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
361
362         if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
363                 update_network(&(pmlmepriv->cur_network.network),
364                                pnetwork, adapter);
365                 r8712_update_protection(adapter,
366                                (pmlmepriv->cur_network.network.IEs) +
367                                sizeof(struct NDIS_802_11_FIXED_IEs),
368                                pmlmepriv->cur_network.network.IELength);
369         }
370 }
371
372 /*
373 Caller must hold pmlmepriv->lock first.
374 */
375 static void update_scanned_network(struct _adapter *adapter,
376                             struct wlan_bssid_ex *target)
377 {
378         struct list_head *plist, *phead;
379
380         u32 bssid_ex_sz;
381         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
382         struct  __queue *queue = &pmlmepriv->scanned_queue;
383         struct wlan_network *pnetwork = NULL;
384         struct wlan_network *oldest = NULL;
385
386         phead = &queue->queue;
387         plist = phead->next;
388
389         while (1) {
390                 if (end_of_queue_search(phead, plist))
391                         break;
392
393                 pnetwork = container_of(plist, struct wlan_network, list);
394                 if (is_same_network(&pnetwork->network, target))
395                         break;
396                 if ((oldest == ((struct wlan_network *)0)) ||
397                     time_after((unsigned long)oldest->last_scanned,
398                                 (unsigned long)pnetwork->last_scanned))
399                         oldest = pnetwork;
400
401                 plist = plist->next;
402         }
403
404
405         /* If we didn't find a match, then get a new network slot to initialize
406          * with this beacon's information
407          */
408         if (end_of_queue_search(phead, plist)) {
409                 if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
410                         /* If there are no more slots, expire the oldest */
411                         pnetwork = oldest;
412                         target->Rssi = (pnetwork->network.Rssi +
413                                         target->Rssi) / 2;
414                         memcpy(&pnetwork->network, target,
415                                 r8712_get_wlan_bssid_ex_sz(target));
416                         pnetwork->last_scanned = jiffies;
417                 } else {
418                         /* Otherwise just pull from the free list */
419                         /* update scan_time */
420                         pnetwork = alloc_network(pmlmepriv);
421                         if (pnetwork == NULL)
422                                 return;
423                         bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
424                         target->Length = bssid_ex_sz;
425                         memcpy(&pnetwork->network, target, bssid_ex_sz);
426                         list_add_tail(&pnetwork->list, &queue->queue);
427                 }
428         } else {
429                 /* we have an entry and we are going to update it. But
430                  * this entry may be already expired. In this case we
431                  * do the same as we found a new net and call the new_net
432                  * handler
433                  */
434                 update_network(&pnetwork->network, target, adapter);
435                 pnetwork->last_scanned = jiffies;
436         }
437 }
438
439 static void rtl8711_add_network(struct _adapter *adapter,
440                          struct wlan_bssid_ex *pnetwork)
441 {
442         unsigned long irqL;
443         struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
444         struct  __queue *queue = &pmlmepriv->scanned_queue;
445
446         spin_lock_irqsave(&queue->lock, irqL);
447         update_current_network(adapter, pnetwork);
448         update_scanned_network(adapter, pnetwork);
449         spin_unlock_irqrestore(&queue->lock, irqL);
450 }
451
452 /*select the desired network based on the capability of the (i)bss.
453  * check items:         (1) security
454  *                      (2) network_type
455  *                      (3) WMM
456  *                      (4) HT
457  *                      (5) others
458  */
459 static int is_desired_network(struct _adapter *adapter,
460                                 struct wlan_network *pnetwork)
461 {
462         u8 wps_ie[512];
463         uint wps_ielen;
464         int bselected = true;
465         struct  security_priv *psecuritypriv = &adapter->securitypriv;
466
467         if (psecuritypriv->wps_phase) {
468                 if (r8712_get_wps_ie(pnetwork->network.IEs,
469                     pnetwork->network.IELength, wps_ie,
470                     &wps_ielen))
471                         return true;
472                 return false;
473         }
474         if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
475                     (pnetwork->network.Privacy == 0))
476                 bselected = false;
477         if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
478                 if (pnetwork->network.InfrastructureMode !=
479                         adapter->mlmepriv.cur_network.network.
480                         InfrastructureMode)
481                         bselected = false;
482         }
483         return bselected;
484 }
485
486 /* TODO: Perry : For Power Management */
487 void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
488 {
489 }
490
491 void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
492 {
493         unsigned long flags;
494         u32 len;
495         struct wlan_bssid_ex *pnetwork;
496         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
497
498         pnetwork = (struct wlan_bssid_ex *)pbuf;
499 #ifdef __BIG_ENDIAN
500         /* endian_convert */
501         pnetwork->Length = le32_to_cpu(pnetwork->Length);
502         pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
503         pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
504         pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
505         pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
506         pnetwork->Configuration.ATIMWindow =
507                  le32_to_cpu(pnetwork->Configuration.ATIMWindow);
508         pnetwork->Configuration.BeaconPeriod =
509                  le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
510         pnetwork->Configuration.DSConfig =
511                  le32_to_cpu(pnetwork->Configuration.DSConfig);
512         pnetwork->Configuration.FHConfig.DwellTime =
513                  le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
514         pnetwork->Configuration.FHConfig.HopPattern =
515                  le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
516         pnetwork->Configuration.FHConfig.HopSet =
517                  le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
518         pnetwork->Configuration.FHConfig.Length =
519                  le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
520         pnetwork->Configuration.Length =
521                  le32_to_cpu(pnetwork->Configuration.Length);
522         pnetwork->InfrastructureMode =
523                  le32_to_cpu(pnetwork->InfrastructureMode);
524         pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
525 #endif
526         len = r8712_get_wlan_bssid_ex_sz(pnetwork);
527         if (len > sizeof(struct wlan_bssid_ex))
528                 return;
529         spin_lock_irqsave(&pmlmepriv->lock2, flags);
530         /* update IBSS_network 's timestamp */
531         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
532                 if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
533                     pnetwork->MacAddress, ETH_ALEN)) {
534                         struct wlan_network *ibss_wlan = NULL;
535
536                         memcpy(pmlmepriv->cur_network.network.IEs,
537                                 pnetwork->IEs, 8);
538                         ibss_wlan = r8712_find_network(
539                                                 &pmlmepriv->scanned_queue,
540                                                 pnetwork->MacAddress);
541                         if (ibss_wlan) {
542                                 memcpy(ibss_wlan->network.IEs,
543                                         pnetwork->IEs, 8);
544                                 goto exit;
545                         }
546                 }
547         }
548         /* lock pmlmepriv->lock when you accessing network_q */
549         if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
550                 if (pnetwork->Ssid.Ssid[0] != 0) {
551                         rtl8711_add_network(adapter, pnetwork);
552                 } else {
553                         pnetwork->Ssid.SsidLength = 8;
554                         memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
555                         rtl8711_add_network(adapter, pnetwork);
556                 }
557         }
558 exit:
559         spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
560 }
561
562 void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
563 {
564         unsigned long irqL;
565         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
566
567         spin_lock_irqsave(&pmlmepriv->lock, irqL);
568
569         if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
570                 del_timer(&pmlmepriv->scan_to_timer);
571
572                 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
573         }
574
575         if (pmlmepriv->to_join) {
576                 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
577                         if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
578                                 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
579
580                                 if (r8712_select_and_join_from_scan(pmlmepriv)
581                                     == _SUCCESS)
582                                         mod_timer(&pmlmepriv->assoc_timer, jiffies +
583                                                   msecs_to_jiffies(MAX_JOIN_TIMEOUT));
584                                 else {
585                                         struct wlan_bssid_ex *pdev_network =
586                                           &(adapter->registrypriv.dev_network);
587                                         u8 *pibss =
588                                                  adapter->registrypriv.
589                                                         dev_network.MacAddress;
590                                         pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
591                                         memcpy(&pdev_network->Ssid,
592                                                 &pmlmepriv->assoc_ssid,
593                                                 sizeof(struct
594                                                          ndis_802_11_ssid));
595                                         r8712_update_registrypriv_dev_network
596                                                 (adapter);
597                                         r8712_generate_random_ibss(pibss);
598                                         pmlmepriv->fw_state =
599                                                  WIFI_ADHOC_MASTER_STATE;
600                                         pmlmepriv->to_join = false;
601                                 }
602                         }
603                 } else {
604                         pmlmepriv->to_join = false;
605                         set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
606                         if (r8712_select_and_join_from_scan(pmlmepriv) ==
607                             _SUCCESS)
608                                 mod_timer(&pmlmepriv->assoc_timer, jiffies +
609                                           msecs_to_jiffies(MAX_JOIN_TIMEOUT));
610                         else
611                                 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
612                 }
613         }
614         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
615 }
616
617 /*
618  *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
619  */
620 void r8712_free_assoc_resources(struct _adapter *adapter)
621 {
622         unsigned long irqL;
623         struct wlan_network *pwlan = NULL;
624         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
625         struct sta_priv *pstapriv = &adapter->stapriv;
626         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
627
628         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
629                                    tgt_network->network.MacAddress);
630
631         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
632                 struct sta_info *psta;
633
634                 psta = r8712_get_stainfo(&adapter->stapriv,
635                                          tgt_network->network.MacAddress);
636
637                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
638                 r8712_free_stainfo(adapter,  psta);
639                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
640         }
641
642         if (check_fwstate(pmlmepriv,
643             WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
644                 r8712_free_all_stainfo(adapter);
645         if (pwlan)
646                 pwlan->fixed = false;
647
648         if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
649              (adapter->stapriv.asoc_sta_count == 1)))
650                 free_network_nolock(pmlmepriv, pwlan);
651 }
652
653 /*
654 *r8712_indicate_connect: the caller has to lock pmlmepriv->lock
655 */
656 void r8712_indicate_connect(struct _adapter *padapter)
657 {
658         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
659
660         pmlmepriv->to_join = false;
661         set_fwstate(pmlmepriv, _FW_LINKED);
662         padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
663         r8712_os_indicate_connect(padapter);
664         if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
665                 mod_timer(&pmlmepriv->dhcp_timer,
666                           jiffies + msecs_to_jiffies(60000));
667 }
668
669
670 /*
671 *r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
672 */
673 void r8712_ind_disconnect(struct _adapter *padapter)
674 {
675         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
676
677         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
678                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
679                 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
680                 r8712_os_indicate_disconnect(padapter);
681         }
682         if (padapter->pwrctrlpriv.pwr_mode !=
683             padapter->registrypriv.power_mgnt) {
684                 del_timer(&pmlmepriv->dhcp_timer);
685                 r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
686                                   padapter->registrypriv.smart_ps);
687         }
688 }
689
690 /*Notes:
691  *pnetwork : returns from r8712_joinbss_event_callback
692  *ptarget_wlan: found from scanned_queue
693  *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
694  *  "ptarget_sta" & "ptarget_wlan" exist.
695  *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
696  * if "ptarget_wlan" exist.
697  *if join_res > 0, update "cur_network->network" from
698  * "pnetwork->network" if (ptarget_wlan !=NULL).
699  */
700 void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
701 {
702         unsigned long irqL = 0, irqL2;
703         struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
704         struct sta_priv *pstapriv = &adapter->stapriv;
705         struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
706         struct wlan_network     *cur_network = &pmlmepriv->cur_network;
707         struct wlan_network     *pcur_wlan = NULL, *ptarget_wlan = NULL;
708         unsigned int            the_same_macaddr = false;
709         struct wlan_network *pnetwork;
710
711         if (sizeof(struct list_head) == 4 * sizeof(u32)) {
712                 pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
713                 if (!pnetwork)
714                         return;
715                 memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
716                        sizeof(struct wlan_network) - 16);
717         } else {
718                 pnetwork = (struct wlan_network *)pbuf;
719         }
720
721 #ifdef __BIG_ENDIAN
722         /* endian_convert */
723         pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
724         pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
725         pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
726         pnetwork->network.Ssid.SsidLength =
727                  le32_to_cpu(pnetwork->network.Ssid.SsidLength);
728         pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
729         pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
730         pnetwork->network.NetworkTypeInUse =
731                  le32_to_cpu(pnetwork->network.NetworkTypeInUse);
732         pnetwork->network.Configuration.ATIMWindow =
733                  le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
734         pnetwork->network.Configuration.BeaconPeriod =
735                  le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
736         pnetwork->network.Configuration.DSConfig =
737                  le32_to_cpu(pnetwork->network.Configuration.DSConfig);
738         pnetwork->network.Configuration.FHConfig.DwellTime =
739                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.
740                              DwellTime);
741         pnetwork->network.Configuration.FHConfig.HopPattern =
742                  le32_to_cpu(pnetwork->network.Configuration.
743                              FHConfig.HopPattern);
744         pnetwork->network.Configuration.FHConfig.HopSet =
745                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
746         pnetwork->network.Configuration.FHConfig.Length =
747                  le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
748         pnetwork->network.Configuration.Length =
749                  le32_to_cpu(pnetwork->network.Configuration.Length);
750         pnetwork->network.InfrastructureMode =
751                  le32_to_cpu(pnetwork->network.InfrastructureMode);
752         pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
753 #endif
754
755         the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
756                                    cur_network->network.MacAddress, ETH_ALEN);
757         pnetwork->network.Length =
758                  r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
759         spin_lock_irqsave(&pmlmepriv->lock, irqL);
760         if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
761                 goto ignore_joinbss_callback;
762         if (pnetwork->join_res > 0) {
763                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
764                         /*s1. find ptarget_wlan*/
765                         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
766                                 if (the_same_macaddr) {
767                                         ptarget_wlan =
768                                             r8712_find_network(&pmlmepriv->
769                                             scanned_queue,
770                                             cur_network->network.MacAddress);
771                                 } else {
772                                         pcur_wlan =
773                                              r8712_find_network(&pmlmepriv->
774                                              scanned_queue,
775                                              cur_network->network.MacAddress);
776                                         pcur_wlan->fixed = false;
777
778                                         pcur_sta = r8712_get_stainfo(pstapriv,
779                                              cur_network->network.MacAddress);
780                                         spin_lock_irqsave(&pstapriv->
781                                                 sta_hash_lock, irqL2);
782                                         r8712_free_stainfo(adapter, pcur_sta);
783                                         spin_unlock_irqrestore(&(pstapriv->
784                                                 sta_hash_lock), irqL2);
785
786                                         ptarget_wlan =
787                                                  r8712_find_network(&pmlmepriv->
788                                                  scanned_queue,
789                                                  pnetwork->network.
790                                                  MacAddress);
791                                         if (ptarget_wlan)
792                                                 ptarget_wlan->fixed = true;
793                                 }
794                         } else {
795                                 ptarget_wlan = r8712_find_network(&pmlmepriv->
796                                                 scanned_queue,
797                                                 pnetwork->network.MacAddress);
798                                 if (ptarget_wlan)
799                                         ptarget_wlan->fixed = true;
800                         }
801
802                         if (ptarget_wlan == NULL) {
803                                 if (check_fwstate(pmlmepriv,
804                                         _FW_UNDER_LINKING))
805                                         pmlmepriv->fw_state ^=
806                                                  _FW_UNDER_LINKING;
807                                 goto ignore_joinbss_callback;
808                         }
809
810                         /*s2. find ptarget_sta & update ptarget_sta*/
811                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
812                                 if (the_same_macaddr) {
813                                         ptarget_sta =
814                                                  r8712_get_stainfo(pstapriv,
815                                                  pnetwork->network.MacAddress);
816                                         if (ptarget_sta == NULL)
817                                                 ptarget_sta =
818                                                  r8712_alloc_stainfo(pstapriv,
819                                                  pnetwork->network.MacAddress);
820                                 } else {
821                                         ptarget_sta =
822                                                  r8712_alloc_stainfo(pstapriv,
823                                                  pnetwork->network.MacAddress);
824                                 }
825                                 if (ptarget_sta) /*update ptarget_sta*/ {
826                                         ptarget_sta->aid = pnetwork->join_res;
827                                         ptarget_sta->qos_option = 1;
828                                         ptarget_sta->mac_id = 5;
829                                         if (adapter->securitypriv.
830                                             AuthAlgrthm == 2) {
831                                                 adapter->securitypriv.
832                                                         binstallGrpkey =
833                                                          false;
834                                                 adapter->securitypriv.
835                                                         busetkipkey =
836                                                          false;
837                                                 adapter->securitypriv.
838                                                         bgrpkey_handshake =
839                                                          false;
840                                                 ptarget_sta->ieee8021x_blocked
841                                                          = true;
842                                                 ptarget_sta->XPrivacy =
843                                                          adapter->securitypriv.
844                                                          PrivacyAlgrthm;
845                                                 memset((u8 *)&ptarget_sta->
846                                                          x_UncstKey,
847                                                          0,
848                                                          sizeof(union Keytype));
849                                                 memset((u8 *)&ptarget_sta->
850                                                          tkiprxmickey,
851                                                          0,
852                                                          sizeof(union Keytype));
853                                                 memset((u8 *)&ptarget_sta->
854                                                          tkiptxmickey,
855                                                          0,
856                                                          sizeof(union Keytype));
857                                                 memset((u8 *)&ptarget_sta->
858                                                          txpn, 0,
859                                                          sizeof(union pn48));
860                                                 memset((u8 *)&ptarget_sta->
861                                                          rxpn, 0,
862                                                          sizeof(union pn48));
863                                         }
864                                 } else {
865                                         if (check_fwstate(pmlmepriv,
866                                             _FW_UNDER_LINKING))
867                                                 pmlmepriv->fw_state ^=
868                                                          _FW_UNDER_LINKING;
869                                         goto ignore_joinbss_callback;
870                                 }
871                         }
872
873                         /*s3. update cur_network & indicate connect*/
874                         memcpy(&cur_network->network, &pnetwork->network,
875                                 pnetwork->network.Length);
876                         cur_network->aid = pnetwork->join_res;
877                         /*update fw_state will clr _FW_UNDER_LINKING*/
878                         switch (pnetwork->network.InfrastructureMode) {
879                         case Ndis802_11Infrastructure:
880                                 pmlmepriv->fw_state = WIFI_STATION_STATE;
881                                 break;
882                         case Ndis802_11IBSS:
883                                 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
884                                 break;
885                         default:
886                                 pmlmepriv->fw_state = WIFI_NULL_STATE;
887                                 break;
888                         }
889                         r8712_update_protection(adapter,
890                                           (cur_network->network.IEs) +
891                                           sizeof(struct NDIS_802_11_FIXED_IEs),
892                                           (cur_network->network.IELength));
893                         /*TODO: update HT_Capability*/
894                         update_ht_cap(adapter, cur_network->network.IEs,
895                                       cur_network->network.IELength);
896                         /*indicate connect*/
897                         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
898                                 r8712_indicate_connect(adapter);
899                         del_timer(&pmlmepriv->assoc_timer);
900                 } else {
901                         goto ignore_joinbss_callback;
902                 }
903         } else {
904                 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
905                         mod_timer(&pmlmepriv->assoc_timer,
906                                   jiffies + msecs_to_jiffies(1));
907                         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
908                 }
909         }
910 ignore_joinbss_callback:
911         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
912         if (sizeof(struct list_head) == 4 * sizeof(u32))
913                 kfree(pnetwork);
914 }
915
916 void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
917 {
918         unsigned long irqL;
919         struct sta_info *psta;
920         struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
921         struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
922
923         /* to do: */
924         if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
925                 return;
926         psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
927         if (psta != NULL) {
928                 /*the sta have been in sta_info_queue => do nothing
929                  *(between drv has received this event before and
930                  * fw have not yet to set key to CAM_ENTRY)
931                  */
932                 return;
933         }
934
935         psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
936         if (psta == NULL)
937                 return;
938         /* to do : init sta_info variable */
939         psta->qos_option = 0;
940         psta->mac_id = le32_to_cpu((uint)pstassoc->cam_id);
941         /* psta->aid = (uint)pstassoc->cam_id; */
942
943         if (adapter->securitypriv.AuthAlgrthm == 2)
944                 psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
945         psta->ieee8021x_blocked = false;
946         spin_lock_irqsave(&pmlmepriv->lock, irqL);
947         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
948             check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
949                 if (adapter->stapriv.asoc_sta_count == 2) {
950                         /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
951                         r8712_indicate_connect(adapter);
952                 }
953         }
954         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
955 }
956
957 void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
958 {
959         unsigned long irqL, irqL2;
960         struct sta_info *psta;
961         struct wlan_network *pwlan = NULL;
962         struct wlan_bssid_ex *pdev_network = NULL;
963         u8 *pibss = NULL;
964         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
965         struct stadel_event *pstadel = (struct stadel_event *)pbuf;
966         struct sta_priv *pstapriv = &adapter->stapriv;
967         struct wlan_network *tgt_network = &pmlmepriv->cur_network;
968
969         spin_lock_irqsave(&pmlmepriv->lock, irqL2);
970         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
971                 r8712_ind_disconnect(adapter);
972                 r8712_free_assoc_resources(adapter);
973         }
974         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
975             WIFI_ADHOC_STATE)) {
976                 psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
977                 spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
978                 r8712_free_stainfo(adapter, psta);
979                 spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
980                 if (adapter->stapriv.asoc_sta_count == 1) {
981                         /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
982                         pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
983                                 tgt_network->network.MacAddress);
984                         if (pwlan) {
985                                 pwlan->fixed = false;
986                                 free_network_nolock(pmlmepriv, pwlan);
987                         }
988                         /*re-create ibss*/
989                         pdev_network = &(adapter->registrypriv.dev_network);
990                         pibss = adapter->registrypriv.dev_network.MacAddress;
991                         memcpy(pdev_network, &tgt_network->network,
992                                 r8712_get_wlan_bssid_ex_sz(&tgt_network->
993                                                         network));
994                         memcpy(&pdev_network->Ssid,
995                                 &pmlmepriv->assoc_ssid,
996                                 sizeof(struct ndis_802_11_ssid));
997                         r8712_update_registrypriv_dev_network(adapter);
998                         r8712_generate_random_ibss(pibss);
999                         if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1000                                 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1001                                 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1002                         }
1003                 }
1004         }
1005         spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
1006 }
1007
1008 void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
1009 {
1010         struct reportpwrstate_parm *preportpwrstate =
1011                          (struct reportpwrstate_parm *)pbuf;
1012
1013         preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
1014         r8712_cpwm_int_hdl(adapter, preportpwrstate);
1015 }
1016
1017 /*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
1018  *       the ADDBA req frame with start seq control = 0 to wifi client after
1019  *       the WPA handshake and the seqence number of following data packet
1020  *      will be 0. In this case, the Rx reorder sequence is not longer than 0
1021  *       and the WiFi client will drop the data with seq number 0.
1022  *      So, the 8712 firmware has to inform driver with receiving the
1023  *       ADDBA-Req frame so that the driver can reset the
1024  *      sequence value of Rx reorder control.
1025  */
1026 void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
1027 {
1028         struct  ADDBA_Req_Report_parm *pAddbareq_pram =
1029                          (struct ADDBA_Req_Report_parm *)pbuf;
1030         struct  sta_info *psta;
1031         struct  sta_priv *pstapriv = &adapter->stapriv;
1032         struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
1033
1034         psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
1035         if (psta) {
1036                 precvreorder_ctrl =
1037                          &psta->recvreorder_ctrl[pAddbareq_pram->tid];
1038                 /* set the indicate_seq to 0xffff so that the rx reorder
1039                  * can store any following data packet.
1040                  */
1041                 precvreorder_ctrl->indicate_seq = 0xffff;
1042         }
1043 }
1044
1045 void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
1046 {
1047         if (!adapter->securitypriv.wps_hw_pbc_pressed)
1048                 adapter->securitypriv.wps_hw_pbc_pressed = true;
1049 }
1050
1051 void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
1052 {
1053         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1054         struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
1055         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1056         u64 current_tx_pkts;
1057         uint current_rx_pkts;
1058
1059         current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
1060                           (psitesurveyctrl->last_tx_pkts);
1061         current_rx_pkts = (adapter->recvpriv.rx_pkts) -
1062                           (psitesurveyctrl->last_rx_pkts);
1063         psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
1064         psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
1065         if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
1066             (current_rx_pkts > pregistrypriv->busy_thresh))
1067                 psitesurveyctrl->traffic_busy = true;
1068         else
1069                 psitesurveyctrl->traffic_busy = false;
1070 }
1071
1072 void _r8712_join_timeout_handler(struct _adapter *adapter)
1073 {
1074         unsigned long irqL;
1075         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1076
1077         if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1078                 return;
1079         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1080         _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1081         pmlmepriv->to_join = false;
1082         if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1083                 r8712_os_indicate_disconnect(adapter);
1084                 _clr_fwstate_(pmlmepriv, _FW_LINKED);
1085         }
1086         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1087                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1088                                   adapter->registrypriv.smart_ps);
1089         }
1090         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1091 }
1092
1093 void r8712_scan_timeout_handler (struct _adapter *adapter)
1094 {
1095         unsigned long irqL;
1096         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1097
1098         spin_lock_irqsave(&pmlmepriv->lock, irqL);
1099         _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1100         pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1101         spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1102 }
1103
1104 void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1105 {
1106         if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1107                 return;
1108         if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1109                 r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1110                             adapter->registrypriv.smart_ps);
1111 }
1112
1113 void _r8712_wdg_timeout_handler(struct _adapter *adapter)
1114 {
1115         r8712_wdg_wk_cmd(adapter);
1116 }
1117
1118 int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1119 {
1120         struct list_head *phead;
1121         unsigned char *dst_ssid, *src_ssid;
1122         struct _adapter *adapter;
1123         struct  __queue *queue = NULL;
1124         struct wlan_network *pnetwork = NULL;
1125         struct wlan_network *pnetwork_max_rssi = NULL;
1126
1127         adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1128         queue = &pmlmepriv->scanned_queue;
1129         phead = &queue->queue;
1130         pmlmepriv->pscanned = phead->next;
1131         while (1) {
1132                 if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1133                         if ((pmlmepriv->assoc_by_rssi) &&
1134                             (pnetwork_max_rssi != NULL)) {
1135                                 pnetwork = pnetwork_max_rssi;
1136                                 goto ask_for_joinbss;
1137                         }
1138                         return _FAIL;
1139                 }
1140                 pnetwork = container_of(pmlmepriv->pscanned,
1141                                         struct wlan_network, list);
1142                 if (pnetwork == NULL)
1143                         return _FAIL;
1144                 pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1145                 if (pmlmepriv->assoc_by_bssid) {
1146                         dst_ssid = pnetwork->network.MacAddress;
1147                         src_ssid = pmlmepriv->assoc_bssid;
1148                         if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1149                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1150                                         if (is_same_network(&pmlmepriv->
1151                                             cur_network.network,
1152                                             &pnetwork->network)) {
1153                                                 _clr_fwstate_(pmlmepriv,
1154                                                         _FW_UNDER_LINKING);
1155                                                 /*r8712_indicate_connect again*/
1156                                                 r8712_indicate_connect(adapter);
1157                                                 return 2;
1158                                         }
1159                                         r8712_disassoc_cmd(adapter);
1160                                         r8712_ind_disconnect(adapter);
1161                                         r8712_free_assoc_resources(adapter);
1162                                 }
1163                                 goto ask_for_joinbss;
1164                         }
1165                 } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1166                         goto ask_for_joinbss;
1167                 }
1168                 dst_ssid = pnetwork->network.Ssid.Ssid;
1169                 src_ssid = pmlmepriv->assoc_ssid.Ssid;
1170                 if ((pnetwork->network.Ssid.SsidLength ==
1171                     pmlmepriv->assoc_ssid.SsidLength) &&
1172                     (!memcmp(dst_ssid, src_ssid,
1173                      pmlmepriv->assoc_ssid.SsidLength))) {
1174                         if (pmlmepriv->assoc_by_rssi) {
1175                                 /* if the ssid is the same, select the bss
1176                                  * which has the max rssi
1177                                  */
1178                                 if (pnetwork_max_rssi) {
1179                                         if (pnetwork->network.Rssi >
1180                                             pnetwork_max_rssi->network.Rssi)
1181                                                 pnetwork_max_rssi = pnetwork;
1182                                 } else {
1183                                         pnetwork_max_rssi = pnetwork;
1184                                 }
1185                         } else if (is_desired_network(adapter, pnetwork)) {
1186                                 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1187                                         r8712_disassoc_cmd(adapter);
1188                                         r8712_free_assoc_resources(adapter);
1189                                 }
1190                                 goto ask_for_joinbss;
1191                         }
1192                 }
1193         }
1194
1195 ask_for_joinbss:
1196         return r8712_joinbss_cmd(adapter, pnetwork);
1197 }
1198
1199 sint r8712_set_auth(struct _adapter *adapter,
1200                     struct security_priv *psecuritypriv)
1201 {
1202         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1203         struct cmd_obj *pcmd;
1204         struct setauth_parm *psetauthparm;
1205
1206         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1207         if (!pcmd)
1208                 return _FAIL;
1209
1210         psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1211         if (!psetauthparm) {
1212                 kfree(pcmd);
1213                 return _FAIL;
1214         }
1215         psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1216         pcmd->cmdcode = _SetAuth_CMD_;
1217         pcmd->parmbuf = (unsigned char *)psetauthparm;
1218         pcmd->cmdsz = sizeof(struct setauth_parm);
1219         pcmd->rsp = NULL;
1220         pcmd->rspsz = 0;
1221         INIT_LIST_HEAD(&pcmd->list);
1222         r8712_enqueue_cmd(pcmdpriv, pcmd);
1223         return _SUCCESS;
1224 }
1225
1226 sint r8712_set_key(struct _adapter *adapter,
1227                    struct security_priv *psecuritypriv,
1228              sint keyid)
1229 {
1230         struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1231         struct cmd_obj *pcmd;
1232         struct setkey_parm *psetkeyparm;
1233         u8 keylen;
1234         sint ret = _SUCCESS;
1235
1236         pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1237         if (!pcmd)
1238                 return _FAIL;
1239         psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1240         if (!psetkeyparm) {
1241                 ret = _FAIL;
1242                 goto err_free_cmd;
1243         }
1244         if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1245                 psetkeyparm->algorithm =
1246                          (u8)psecuritypriv->XGrpPrivacy;
1247         } else { /* WEP */
1248                 psetkeyparm->algorithm =
1249                          (u8)psecuritypriv->PrivacyAlgrthm;
1250         }
1251         psetkeyparm->keyid = (u8)keyid;
1252
1253         switch (psetkeyparm->algorithm) {
1254         case _WEP40_:
1255                 keylen = 5;
1256                 memcpy(psetkeyparm->key,
1257                         psecuritypriv->DefKey[keyid].skey, keylen);
1258                 break;
1259         case _WEP104_:
1260                 keylen = 13;
1261                 memcpy(psetkeyparm->key,
1262                         psecuritypriv->DefKey[keyid].skey, keylen);
1263                 break;
1264         case _TKIP_:
1265                 if (keyid < 1 || keyid > 2) {
1266                         ret = _FAIL;
1267                         goto err_free_parm;
1268                 }
1269                 keylen = 16;
1270                 memcpy(psetkeyparm->key,
1271                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1272                 psetkeyparm->grpkey = 1;
1273                 break;
1274         case _AES_:
1275                 if (keyid < 1 || keyid > 2) {
1276                         ret = _FAIL;
1277                         goto err_free_parm;
1278                 }
1279                 keylen = 16;
1280                 memcpy(psetkeyparm->key,
1281                         &psecuritypriv->XGrpKey[keyid - 1], keylen);
1282                 psetkeyparm->grpkey = 1;
1283                 break;
1284         default:
1285                 ret = _FAIL;
1286                 goto err_free_parm;
1287         }
1288         pcmd->cmdcode = _SetKey_CMD_;
1289         pcmd->parmbuf = (u8 *)psetkeyparm;
1290         pcmd->cmdsz =  (sizeof(struct setkey_parm));
1291         pcmd->rsp = NULL;
1292         pcmd->rspsz = 0;
1293         INIT_LIST_HEAD(&pcmd->list);
1294         r8712_enqueue_cmd(pcmdpriv, pcmd);
1295         return ret;
1296
1297 err_free_parm:
1298         kfree(psetkeyparm);
1299 err_free_cmd:
1300         kfree(pcmd);
1301         return ret;
1302 }
1303
1304 /* adjust IEs for r8712_joinbss_cmd in WMM */
1305 int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1306                     uint in_len, uint initial_out_len)
1307 {
1308         unsigned int ielength = 0;
1309         unsigned int i, j;
1310
1311         i = 12; /* after the fixed IE */
1312         while (i < in_len) {
1313                 ielength = initial_out_len;
1314                 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1315                     in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1316                     in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1317                         /*WMM element ID and OUI*/
1318                         for (j = i; j < i + 9; j++) {
1319                                 out_ie[ielength] = in_ie[j];
1320                                 ielength++;
1321                         }
1322                         out_ie[initial_out_len + 1] = 0x07;
1323                         out_ie[initial_out_len + 6] = 0x00;
1324                         out_ie[initial_out_len + 8] = 0x00;
1325                         break;
1326                 }
1327                 i += (in_ie[i + 1] + 2); /* to the next IE element */
1328         }
1329         return ielength;
1330 }
1331
1332 /*
1333  * Ported from 8185: IsInPreAuthKeyList().
1334  *
1335  * Search by BSSID,
1336  * Return Value:
1337  *      -1              :if there is no pre-auth key in the  table
1338  *      >=0             :if there is pre-auth key, and   return the entry id
1339  */
1340 static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1341 {
1342         struct security_priv *psecuritypriv = &Adapter->securitypriv;
1343         int i = 0;
1344
1345         do {
1346                 if (psecuritypriv->PMKIDList[i].bUsed &&
1347                    (!memcmp(psecuritypriv->PMKIDList[i].Bssid,
1348                             bssid, ETH_ALEN)))
1349                         break;
1350                 else
1351                         i++;
1352         } while (i < NUM_PMKID_CACHE);
1353
1354         if (i == NUM_PMKID_CACHE) {
1355                 i = -1; /* Could not find. */
1356         } else {
1357                 ; /* There is one Pre-Authentication Key for the
1358                    * specific BSSID.
1359                    */
1360         }
1361         return i;
1362 }
1363
1364 sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1365                      u8 *out_ie, uint in_len)
1366 {
1367         u8 authmode = 0, match;
1368         u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
1369         u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1370         uint ielength, cnt, remove_cnt;
1371         int iEntry;
1372         struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1373         struct security_priv *psecuritypriv = &adapter->securitypriv;
1374         uint ndisauthmode = psecuritypriv->ndisauthtype;
1375         uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1376
1377         if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1378             (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1379                 authmode = _WPA_IE_ID_;
1380                 uncst_oui[0] = 0x0;
1381                 uncst_oui[1] = 0x50;
1382                 uncst_oui[2] = 0xf2;
1383         }
1384         if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1385             (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1386                 authmode = _WPA2_IE_ID_;
1387                 uncst_oui[0] = 0x0;
1388                 uncst_oui[1] = 0x0f;
1389                 uncst_oui[2] = 0xac;
1390         }
1391         switch (ndissecuritytype) {
1392         case Ndis802_11Encryption1Enabled:
1393         case Ndis802_11Encryption1KeyAbsent:
1394                 uncst_oui[3] = 0x1;
1395                 break;
1396         case Ndis802_11Encryption2Enabled:
1397         case Ndis802_11Encryption2KeyAbsent:
1398                 uncst_oui[3] = 0x2;
1399                 break;
1400         case Ndis802_11Encryption3Enabled:
1401         case Ndis802_11Encryption3KeyAbsent:
1402                 uncst_oui[3] = 0x4;
1403                 break;
1404         default:
1405                 break;
1406         }
1407         /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1408         cnt = 12;
1409         match = false;
1410         while (cnt < in_len) {
1411                 if (in_ie[cnt] == authmode) {
1412                         if ((authmode == _WPA_IE_ID_) &&
1413                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1414                                 memcpy(&sec_ie[0], &in_ie[cnt],
1415                                         in_ie[cnt + 1] + 2);
1416                                 match = true;
1417                                 break;
1418                         }
1419                         if (authmode == _WPA2_IE_ID_) {
1420                                 memcpy(&sec_ie[0], &in_ie[cnt],
1421                                         in_ie[cnt + 1] + 2);
1422                                 match = true;
1423                                 break;
1424                         }
1425                         if (((authmode == _WPA_IE_ID_) &&
1426                              (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1427                              (authmode == _WPA2_IE_ID_))
1428                                 memcpy(&bkup_ie[0], &in_ie[cnt],
1429                                         in_ie[cnt + 1] + 2);
1430                 }
1431                 cnt += in_ie[cnt + 1] + 2; /*get next*/
1432         }
1433         /*restruct WPA IE or WPA2 IE in sec_ie[] */
1434         if (match) {
1435                 if (sec_ie[0] == _WPA_IE_ID_) {
1436                         /* parsing SSN IE to select required encryption
1437                          * algorithm, and set the bc/mc encryption algorithm
1438                          */
1439                         while (true) {
1440                                 /*check wpa_oui tag*/
1441                                 if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1442                                         match = false;
1443                                         break;
1444                                 }
1445                                 if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1446                                         /*IE Ver error*/
1447                                         match = false;
1448                                         break;
1449                                 }
1450                                 if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1451                                         /* get bc/mc encryption type (group
1452                                          * key type)
1453                                          */
1454                                         switch (sec_ie[11]) {
1455                                         case 0x0: /*none*/
1456                                                 psecuritypriv->XGrpPrivacy =
1457                                                                 _NO_PRIVACY_;
1458                                                 break;
1459                                         case 0x1: /*WEP_40*/
1460                                                 psecuritypriv->XGrpPrivacy =
1461                                                                 _WEP40_;
1462                                                 break;
1463                                         case 0x2: /*TKIP*/
1464                                                 psecuritypriv->XGrpPrivacy =
1465                                                                 _TKIP_;
1466                                                 break;
1467                                         case 0x3: /*AESCCMP*/
1468                                         case 0x4:
1469                                                 psecuritypriv->XGrpPrivacy =
1470                                                                 _AES_;
1471                                                 break;
1472                                         case 0x5: /*WEP_104*/
1473                                                 psecuritypriv->XGrpPrivacy =
1474                                                                 _WEP104_;
1475                                                 break;
1476                                         }
1477                                 } else {
1478                                         match = false;
1479                                         break;
1480                                 }
1481                                 if (sec_ie[12] == 0x01) {
1482                                         /*check the unicast encryption type*/
1483                                         if (memcmp(&sec_ie[14],
1484                                             &uncst_oui[0], 4)) {
1485                                                 match = false;
1486                                                 break;
1487
1488                                         } /*else the uncst_oui is match*/
1489                                 } else { /*mixed mode, unicast_enc_type > 1*/
1490                                         /*select the uncst_oui and remove
1491                                          * the other uncst_oui
1492                                          */
1493                                         cnt = sec_ie[12];
1494                                         remove_cnt = (cnt - 1) * 4;
1495                                         sec_ie[12] = 0x01;
1496                                         memcpy(&sec_ie[14], &uncst_oui[0], 4);
1497                                         /*remove the other unicast suit*/
1498                                         memcpy(&sec_ie[18],
1499                                                 &sec_ie[18 + remove_cnt],
1500                                                 sec_ie[1] - 18 + 2 -
1501                                                 remove_cnt);
1502                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1503                                 }
1504                                 break;
1505                         }
1506                 }
1507                 if (authmode == _WPA2_IE_ID_) {
1508                         /* parsing RSN IE to select required encryption
1509                          * algorithm, and set the bc/mc encryption algorithm
1510                          */
1511                         while (true) {
1512                                 if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1513                                         /*IE Ver error*/
1514                                         match = false;
1515                                         break;
1516                                 }
1517                                 if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1518                                         /*get bc/mc encryption type*/
1519                                         switch (sec_ie[7]) {
1520                                         case 0x1: /*WEP_40*/
1521                                                 psecuritypriv->XGrpPrivacy =
1522                                                                 _WEP40_;
1523                                                 break;
1524                                         case 0x2: /*TKIP*/
1525                                                 psecuritypriv->XGrpPrivacy =
1526                                                                 _TKIP_;
1527                                                 break;
1528                                         case 0x4: /*AESWRAP*/
1529                                                 psecuritypriv->XGrpPrivacy =
1530                                                                 _AES_;
1531                                                 break;
1532                                         case 0x5: /*WEP_104*/
1533                                                 psecuritypriv->XGrpPrivacy =
1534                                                                 _WEP104_;
1535                                                 break;
1536                                         default: /*one*/
1537                                                 psecuritypriv->XGrpPrivacy =
1538                                                                 _NO_PRIVACY_;
1539                                                 break;
1540                                         }
1541                                 } else {
1542                                         match = false;
1543                                         break;
1544                                 }
1545                                 if (sec_ie[8] == 0x01) {
1546                                         /*check the unicast encryption type*/
1547                                         if (memcmp(&sec_ie[10],
1548                                                      &uncst_oui[0], 4)) {
1549                                                 match = false;
1550                                                 break;
1551                                         } /*else the uncst_oui is match*/
1552                                 } else { /*mixed mode, unicast_enc_type > 1*/
1553                                         /*select the uncst_oui and remove the
1554                                          * other uncst_oui
1555                                          */
1556                                         cnt = sec_ie[8];
1557                                         remove_cnt = (cnt - 1) * 4;
1558                                         sec_ie[8] = 0x01;
1559                                         memcpy(&sec_ie[10], &uncst_oui[0], 4);
1560                                         /*remove the other unicast suit*/
1561                                         memcpy(&sec_ie[14],
1562                                                 &sec_ie[14 + remove_cnt],
1563                                                 (sec_ie[1] - 14 + 2 -
1564                                                 remove_cnt));
1565                                         sec_ie[1] = sec_ie[1] - remove_cnt;
1566                                 }
1567                                 break;
1568                         }
1569                 }
1570         }
1571         if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1572                 /*copy fixed ie*/
1573                 memcpy(out_ie, in_ie, 12);
1574                 ielength = 12;
1575                 /*copy RSN or SSN*/
1576                 if (match) {
1577                         memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1578                         ielength += sec_ie[1] + 2;
1579                         if (authmode == _WPA2_IE_ID_) {
1580                                 /*the Pre-Authentication bit should be zero*/
1581                                 out_ie[ielength - 1] = 0;
1582                                 out_ie[ielength - 2] = 0;
1583                         }
1584                         r8712_report_sec_ie(adapter, authmode, sec_ie);
1585                 }
1586         } else {
1587                 /*copy fixed ie only*/
1588                 memcpy(out_ie, in_ie, 12);
1589                 ielength = 12;
1590                 if (psecuritypriv->wps_phase) {
1591                         memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1592                                psecuritypriv->wps_ie_len);
1593                         ielength += psecuritypriv->wps_ie_len;
1594                 }
1595         }
1596         iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1597         if (iEntry < 0)
1598                 return ielength;
1599         if (authmode == _WPA2_IE_ID_) {
1600                 out_ie[ielength] = 1;
1601                 ielength++;
1602                 out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1603                 ielength++;
1604                 memcpy(&out_ie[ielength],
1605                         &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1606                 ielength += 16;
1607                 out_ie[13] += 18;/*PMKID length = 2+16*/
1608         }
1609         return ielength;
1610 }
1611
1612 void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1613 {
1614         struct registry_priv *pregistrypriv = &adapter->registrypriv;
1615         struct eeprom_priv *peepriv = &adapter->eeprompriv;
1616         struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1617         u8 *myhwaddr = myid(peepriv);
1618
1619         memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1620         memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1621                 sizeof(struct ndis_802_11_ssid));
1622         pdev_network->Configuration.Length =
1623                          sizeof(struct NDIS_802_11_CONFIGURATION);
1624         pdev_network->Configuration.BeaconPeriod = 100;
1625         pdev_network->Configuration.FHConfig.Length = 0;
1626         pdev_network->Configuration.FHConfig.HopPattern = 0;
1627         pdev_network->Configuration.FHConfig.HopSet = 0;
1628         pdev_network->Configuration.FHConfig.DwellTime = 0;
1629 }
1630
1631 void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1632 {
1633         int sz = 0;
1634         struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1635         struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1636         struct security_priv    *psecuritypriv = &adapter->securitypriv;
1637         struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1638
1639         pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1640                                             > 0 ? 1 : 0); /* adhoc no 802.1x */
1641         pdev_network->Rssi = 0;
1642         switch (pregistrypriv->wireless_mode) {
1643         case WIRELESS_11B:
1644                 pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11DS);
1645                 break;
1646         case WIRELESS_11G:
1647         case WIRELESS_11BG:
1648                 pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11OFDM24);
1649                 break;
1650         case WIRELESS_11A:
1651                 pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11OFDM5);
1652                 break;
1653         default:
1654                 /* TODO */
1655                 break;
1656         }
1657         pdev_network->Configuration.DSConfig = cpu_to_le32(
1658                                                pregistrypriv->channel);
1659         if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1660                 pdev_network->Configuration.ATIMWindow = cpu_to_le32(3);
1661         pdev_network->InfrastructureMode = cpu_to_le32(
1662                                 cur_network->network.InfrastructureMode);
1663         /* 1. Supported rates
1664          * 2. IE
1665          */
1666         sz = r8712_generate_ie(pregistrypriv);
1667         pdev_network->IELength = sz;
1668         pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1669 }
1670
1671 /*the function is at passive_level*/
1672 void r8712_joinbss_reset(struct _adapter *padapter)
1673 {
1674         int i;
1675         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1676         struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1677
1678         /* todo: if you want to do something io/reg/hw setting before join_bss,
1679          * please add code here
1680          */
1681         phtpriv->ampdu_enable = false;/*reset to disabled*/
1682         for (i = 0; i < 16; i++)
1683                 phtpriv->baddbareq_issued[i] = false;/*reset it*/
1684         if (phtpriv->ht_option) {
1685                 /* validate  usb rx aggregation */
1686                 r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1687         } else {
1688                 /* invalidate  usb rx aggregation */
1689                 /* TH=1 => means that invalidate usb rx aggregation */
1690                 r8712_write8(padapter, 0x102500D9, 1);
1691         }
1692 }
1693
1694 /*the function is >= passive_level*/
1695 unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1696                                      u8 *out_ie, uint in_len, uint *pout_len)
1697 {
1698         u32 ielen, out_len;
1699         unsigned char *p;
1700         struct ieee80211_ht_cap ht_capie;
1701         unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1702         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1703         struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1704         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1705
1706         phtpriv->ht_option = 0;
1707         p = r8712_get_ie(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
1708         if (p && (ielen > 0)) {
1709                 if (pqospriv->qos_option == 0) {
1710                         out_len = *pout_len;
1711                         r8712_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_,
1712                                      _WMM_IE_Length_, WMM_IE, pout_len);
1713                         pqospriv->qos_option = 1;
1714                 }
1715                 out_len = *pout_len;
1716                 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1717                 ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |
1718                                     IEEE80211_HT_CAP_SGI_20 |
1719                                     IEEE80211_HT_CAP_SGI_40 |
1720                                     IEEE80211_HT_CAP_TX_STBC |
1721                                     IEEE80211_HT_CAP_MAX_AMSDU |
1722                                     IEEE80211_HT_CAP_DSSSCCK40;
1723                 ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR &
1724                                 0x03) | (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
1725                 r8712_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_,
1726                              sizeof(struct ieee80211_ht_cap),
1727                              (unsigned char *)&ht_capie, pout_len);
1728                 phtpriv->ht_option = 1;
1729         }
1730         return phtpriv->ht_option;
1731 }
1732
1733 /* the function is > passive_level (in critical_section) */
1734 static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1735 {
1736         u8 *p, max_ampdu_sz;
1737         int i, len;
1738         struct sta_info *bmc_sta, *psta;
1739         struct ieee80211_ht_cap *pht_capie;
1740         struct recv_reorder_ctrl *preorder_ctrl;
1741         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1742         struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1743         struct registry_priv *pregistrypriv = &padapter->registrypriv;
1744         struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1745
1746         if (!phtpriv->ht_option)
1747                 return;
1748         /* maybe needs check if ap supports rx ampdu. */
1749         if (!phtpriv->ampdu_enable &&
1750             (pregistrypriv->ampdu_enable == 1))
1751                 phtpriv->ampdu_enable = true;
1752         /*check Max Rx A-MPDU Size*/
1753         len = 0;
1754         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1755                                 _HT_CAPABILITY_IE_,
1756                                 &len, ie_len -
1757                                 sizeof(struct NDIS_802_11_FIXED_IEs));
1758         if (p && len > 0) {
1759                 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1760                 max_ampdu_sz = (pht_capie->ampdu_params_info &
1761                                 IEEE80211_HT_CAP_AMPDU_FACTOR);
1762                 /* max_ampdu_sz (kbytes); */
1763                 max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1764                 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1765         }
1766         /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1767          * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1768          * wstart_b(indicate_seq) to default value=0xffff
1769          * todo: check if AP can send A-MPDU packets
1770          */
1771         bmc_sta = r8712_get_bcmc_stainfo(padapter);
1772         if (bmc_sta) {
1773                 for (i = 0; i < 16; i++) {
1774                         preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1775                         preorder_ctrl->indicate_seq = 0xffff;
1776                         preorder_ctrl->wend_b = 0xffff;
1777                 }
1778         }
1779         psta = r8712_get_stainfo(&padapter->stapriv,
1780                                  pcur_network->network.MacAddress);
1781         if (psta) {
1782                 for (i = 0; i < 16; i++) {
1783                         preorder_ctrl = &psta->recvreorder_ctrl[i];
1784                         preorder_ctrl->indicate_seq = 0xffff;
1785                         preorder_ctrl->wend_b = 0xffff;
1786                 }
1787         }
1788         len = 0;
1789         p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1790                    _HT_ADD_INFO_IE_, &len,
1791                    ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1792 }
1793
1794 void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1795 {
1796         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1797         struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1798
1799         if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1800                 if (!phtpriv->baddbareq_issued[priority]) {
1801                         r8712_addbareq_cmd(padapter, (u8)priority);
1802                         phtpriv->baddbareq_issued[priority] = true;
1803                 }
1804         }
1805 }