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