root/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ieee80211_is_54g
  2. ieee80211_is_shortslot
  3. ieee80211_MFIE_rate_len
  4. ieee80211_MFIE_Brate
  5. ieee80211_MFIE_Grate
  6. ieee80211_WMM_Info
  7. ieee80211_TURBO_Info
  8. enqueue_mgmt
  9. dequeue_mgmt
  10. init_mgmt_queue
  11. MgntQuery_MgntFrameTxRate
  12. softmac_mgmt_xmit
  13. softmac_ps_mgmt_xmit
  14. ieee80211_probe_req
  15. ieee80211_send_beacon
  16. ieee80211_send_beacon_cb
  17. ieee80211_send_probe
  18. ieee80211_send_probe_requests
  19. ieee80211_softmac_scan_syncro
  20. ieee80211_softmac_scan_wq
  21. ieee80211_beacons_start
  22. ieee80211_beacons_stop
  23. ieee80211_stop_send_beacons
  24. ieee80211_start_send_beacons
  25. ieee80211_softmac_stop_scan
  26. ieee80211_stop_scan
  27. ieee80211_start_scan
  28. ieee80211_start_scan_syncro
  29. ieee80211_authentication_req
  30. ieee80211_probe_resp
  31. ieee80211_assoc_resp
  32. ieee80211_auth_resp
  33. ieee80211_null_func
  34. ieee80211_resp_to_assoc_rq
  35. ieee80211_resp_to_auth
  36. ieee80211_resp_to_probe
  37. ieee80211_association_req
  38. ieee80211_associate_abort
  39. ieee80211_associate_abort_cb
  40. ieee80211_associate_step1
  41. ieee80211_auth_challenge
  42. ieee80211_associate_step2
  43. ieee80211_associate_complete_wq
  44. ieee80211_associate_complete
  45. ieee80211_associate_procedure_wq
  46. ieee80211_softmac_new_net
  47. ieee80211_softmac_check_all_nets
  48. auth_parse
  49. auth_rq_parse
  50. probe_rq_parse
  51. assoc_rq_parse
  52. assoc_parse
  53. ieee80211_rx_probe_rq
  54. ieee80211_rx_auth_rq
  55. ieee80211_rx_assoc_rq
  56. ieee80211_sta_ps_send_null_frame
  57. ieee80211_sta_ps_sleep
  58. ieee80211_sta_ps
  59. ieee80211_sta_wakeup
  60. ieee80211_ps_tx_ack
  61. ieee80211_process_action
  62. ieee80211_check_auth_response
  63. ieee80211_rx_frame_softmac
  64. ieee80211_softmac_xmit
  65. ieee80211_resume_tx
  66. ieee80211_reset_queue
  67. ieee80211_wake_queue
  68. ieee80211_stop_queue
  69. ieee80211_start_master_bss
  70. ieee80211_start_monitor_mode
  71. ieee80211_start_ibss_wq
  72. ieee80211_start_ibss
  73. ieee80211_start_bss
  74. ieee80211_disassociate
  75. ieee80211_associate_retry_wq
  76. ieee80211_get_beacon_
  77. ieee80211_get_beacon
  78. ieee80211_softmac_stop_protocol
  79. ieee80211_stop_protocol
  80. ieee80211_softmac_start_protocol
  81. ieee80211_start_protocol
  82. ieee80211_softmac_init
  83. ieee80211_softmac_free
  84. ieee80211_wpa_enable
  85. ieee80211_wpa_assoc_frame
  86. ieee80211_wpa_mlme
  87. ieee80211_wpa_set_wpa_ie
  88. ieee80211_wpa_set_auth_algs
  89. ieee80211_wpa_set_param
  90. ieee80211_wpa_set_encryption
  91. ieee80211_disassociate_skb
  92. SendDisassociation
  93. ieee80211_wpa_supplicant_ioctl
  94. notify_wx_assoc_event

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* IEEE 802.11 SoftMAC layer
   3  * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
   4  *
   5  * Mostly extracted from the rtl8180-sa2400 driver for the
   6  * in-kernel generic ieee802.11 stack.
   7  *
   8  * Few lines might be stolen from other part of the ieee80211
   9  * stack. Copyright who own it's copyright
  10  *
  11  * WPA code stolen from the ipw2200 driver.
  12  * Copyright who own it's copyright.
  13  */
  14 #include "ieee80211.h"
  15 
  16 #include <linux/random.h>
  17 #include <linux/delay.h>
  18 #include <linux/slab.h>
  19 #include <linux/uaccess.h>
  20 #include <linux/etherdevice.h>
  21 
  22 #include "dot11d.h"
  23 
  24 short ieee80211_is_54g(const struct ieee80211_network *net)
  25 {
  26         return (net->rates_ex_len > 0) || (net->rates_len > 4);
  27 }
  28 EXPORT_SYMBOL(ieee80211_is_54g);
  29 
  30 short ieee80211_is_shortslot(const struct ieee80211_network *net)
  31 {
  32         return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
  33 }
  34 EXPORT_SYMBOL(ieee80211_is_shortslot);
  35 
  36 /* returns the total length needed for pleacing the RATE MFIE
  37  * tag and the EXTENDED RATE MFIE tag if needed.
  38  * It encludes two bytes per tag for the tag itself and its len
  39  */
  40 static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
  41 {
  42         unsigned int rate_len = 0;
  43 
  44         if (ieee->modulation & IEEE80211_CCK_MODULATION)
  45                 rate_len = IEEE80211_CCK_RATE_LEN + 2;
  46 
  47         if (ieee->modulation & IEEE80211_OFDM_MODULATION)
  48                 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
  49 
  50         return rate_len;
  51 }
  52 
  53 /* pleace the MFIE rate, tag to the memory (double) poined.
  54  * Then it updates the pointer so that
  55  * it points after the new MFIE tag added.
  56  */
  57 static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
  58 {
  59         u8 *tag = *tag_p;
  60 
  61         if (ieee->modulation & IEEE80211_CCK_MODULATION) {
  62                 *tag++ = MFIE_TYPE_RATES;
  63                 *tag++ = 4;
  64                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
  65                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
  66                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
  67                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
  68         }
  69 
  70         /* We may add an option for custom rates that specific HW might support */
  71         *tag_p = tag;
  72 }
  73 
  74 static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
  75 {
  76         u8 *tag = *tag_p;
  77 
  78         if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
  79                 *tag++ = MFIE_TYPE_RATES_EX;
  80                 *tag++ = 8;
  81                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
  82                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
  83                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
  84                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
  85                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
  86                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
  87                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
  88                 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
  89         }
  90 
  91         /* We may add an option for custom rates that specific HW might support */
  92         *tag_p = tag;
  93 }
  94 
  95 static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
  96 {
  97         u8 *tag = *tag_p;
  98 
  99         *tag++ = MFIE_TYPE_GENERIC; /* 0 */
 100         *tag++ = 7;
 101         *tag++ = 0x00;
 102         *tag++ = 0x50;
 103         *tag++ = 0xf2;
 104         *tag++ = 0x02;  /* 5 */
 105         *tag++ = 0x00;
 106         *tag++ = 0x01;
 107 #ifdef SUPPORT_USPD
 108         if (ieee->current_network.wmm_info & 0x80)
 109                 *tag++ = 0x0f | MAX_SP_Len;
 110         else
 111                 *tag++ = MAX_SP_Len;
 112 #else
 113         *tag++ = MAX_SP_Len;
 114 #endif
 115         *tag_p = tag;
 116 }
 117 
 118 #ifdef THOMAS_TURBO
 119 static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p)
 120 {
 121         u8 *tag = *tag_p;
 122 
 123         *tag++ = MFIE_TYPE_GENERIC; /* 0 */
 124         *tag++ = 7;
 125         *tag++ = 0x00;
 126         *tag++ = 0xe0;
 127         *tag++ = 0x4c;
 128         *tag++ = 0x01;  /* 5 */
 129         *tag++ = 0x02;
 130         *tag++ = 0x11;
 131         *tag++ = 0x00;
 132 
 133         *tag_p = tag;
 134         printk(KERN_ALERT "This is enable turbo mode IE process\n");
 135 }
 136 #endif
 137 
 138 static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
 139 {
 140         int nh;
 141 
 142         nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM;
 143 
 144 /*
 145  * if the queue is full but we have newer frames then
 146  * just overwrites the oldest.
 147  *
 148  * if (nh == ieee->mgmt_queue_tail)
 149  *              return -1;
 150  */
 151         ieee->mgmt_queue_head = nh;
 152         ieee->mgmt_queue_ring[nh] = skb;
 153 
 154         //return 0;
 155 }
 156 
 157 static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
 158 {
 159         struct sk_buff *ret;
 160 
 161         if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
 162                 return NULL;
 163 
 164         ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
 165 
 166         ieee->mgmt_queue_tail =
 167                 (ieee->mgmt_queue_tail + 1) % MGMT_QUEUE_NUM;
 168 
 169         return ret;
 170 }
 171 
 172 static void init_mgmt_queue(struct ieee80211_device *ieee)
 173 {
 174         ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
 175 }
 176 
 177 static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
 178 {
 179         PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
 180         u8 rate;
 181 
 182         /* 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. */
 183         if (pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
 184                 rate = 0x0c;
 185         else
 186                 rate = ieee->basic_rate & 0x7f;
 187 
 188         if (rate == 0) {
 189                 /* 2005.01.26, by rcnjko. */
 190                 if (ieee->mode == IEEE_A ||
 191                     ieee->mode == IEEE_N_5G ||
 192                     (ieee->mode == IEEE_N_24G && !pHTInfo->bCurSuppCCK))
 193                         rate = 0x0c;
 194                 else
 195                         rate = 0x02;
 196         }
 197 
 198         /*
 199         // Data rate of ProbeReq is already decided. Annie, 2005-03-31
 200         if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) ) {
 201         if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
 202         rate = 0x0c;
 203         else
 204         rate = 0x02;
 205         }
 206          */
 207         return rate;
 208 }
 209 
 210 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
 211 
 212 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
 213 {
 214         unsigned long flags;
 215         short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
 216         struct rtl_80211_hdr_3addr  *header =
 217                 (struct rtl_80211_hdr_3addr  *)skb->data;
 218 
 219         struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 220 
 221         spin_lock_irqsave(&ieee->lock, flags);
 222 
 223         /* called with 2nd param 0, no mgmt lock required */
 224         ieee80211_sta_wakeup(ieee, 0);
 225 
 226         tcb_desc->queue_index = MGNT_QUEUE;
 227         tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
 228         tcb_desc->RATRIndex = 7;
 229         tcb_desc->bTxDisableRateFallBack = 1;
 230         tcb_desc->bTxUseDriverAssingedRate = 1;
 231 
 232         if (single) {
 233                 if (ieee->queue_stop) {
 234                         enqueue_mgmt(ieee, skb);
 235                 } else {
 236                         header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
 237 
 238                         if (ieee->seq_ctrl[0] == 0xFFF)
 239                                 ieee->seq_ctrl[0] = 0;
 240                         else
 241                                 ieee->seq_ctrl[0]++;
 242 
 243                         /* avoid watchdog triggers */
 244                         netif_trans_update(ieee->dev);
 245                         ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
 246                         //dev_kfree_skb_any(skb);//edit by thomas
 247                 }
 248 
 249                 spin_unlock_irqrestore(&ieee->lock, flags);
 250         } else {
 251                 spin_unlock_irqrestore(&ieee->lock, flags);
 252                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
 253 
 254                 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
 255 
 256                 if (ieee->seq_ctrl[0] == 0xFFF)
 257                         ieee->seq_ctrl[0] = 0;
 258                 else
 259                         ieee->seq_ctrl[0]++;
 260 
 261                 /* check whether the managed packet queued greater than 5 */
 262                 if (!ieee->check_nic_enough_desc(ieee->dev, tcb_desc->queue_index) || \
 263                     (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0) || \
 264                     (ieee->queue_stop)) {
 265                         /* insert the skb packet to the management queue */
 266                         /* as for the completion function, it does not need
 267                          * to check it any more.
 268                          * */
 269                         printk("%s():insert to waitqueue!\n", __func__);
 270                         skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
 271                 } else {
 272                         ieee->softmac_hard_start_xmit(skb, ieee->dev);
 273                         //dev_kfree_skb_any(skb);//edit by thomas
 274                 }
 275                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
 276         }
 277 }
 278 
 279 static inline void
 280 softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
 281 {
 282         short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
 283         struct rtl_80211_hdr_3addr  *header =
 284                 (struct rtl_80211_hdr_3addr  *)skb->data;
 285 
 286         if (single) {
 287                 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
 288 
 289                 if (ieee->seq_ctrl[0] == 0xFFF)
 290                         ieee->seq_ctrl[0] = 0;
 291                 else
 292                         ieee->seq_ctrl[0]++;
 293 
 294                 /* avoid watchdog triggers */
 295                 netif_trans_update(ieee->dev);
 296                 ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
 297         } else {
 298                 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
 299 
 300                 if (ieee->seq_ctrl[0] == 0xFFF)
 301                         ieee->seq_ctrl[0] = 0;
 302                 else
 303                         ieee->seq_ctrl[0]++;
 304 
 305                 ieee->softmac_hard_start_xmit(skb, ieee->dev);
 306         }
 307         //dev_kfree_skb_any(skb);//edit by thomas
 308 }
 309 
 310 static inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
 311 {
 312         unsigned int len, rate_len;
 313         u8 *tag;
 314         struct sk_buff *skb;
 315         struct ieee80211_probe_request *req;
 316 
 317         len = ieee->current_network.ssid_len;
 318 
 319         rate_len = ieee80211_MFIE_rate_len(ieee);
 320 
 321         skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
 322                             2 + len + rate_len + ieee->tx_headroom);
 323         if (!skb)
 324                 return NULL;
 325 
 326         skb_reserve(skb, ieee->tx_headroom);
 327 
 328         req = skb_put(skb, sizeof(struct ieee80211_probe_request));
 329         req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
 330         req->header.duration_id = 0; /* FIXME: is this OK? */
 331 
 332         eth_broadcast_addr(req->header.addr1);
 333         memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 334         eth_broadcast_addr(req->header.addr3);
 335 
 336         tag = skb_put(skb, len + 2 + rate_len);
 337 
 338         *tag++ = MFIE_TYPE_SSID;
 339         *tag++ = len;
 340         memcpy(tag, ieee->current_network.ssid, len);
 341         tag += len;
 342 
 343         ieee80211_MFIE_Brate(ieee, &tag);
 344         ieee80211_MFIE_Grate(ieee, &tag);
 345         return skb;
 346 }
 347 
 348 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
 349 
 350 static void ieee80211_send_beacon(struct ieee80211_device *ieee)
 351 {
 352         struct sk_buff *skb;
 353 
 354         if (!ieee->ieee_up)
 355                 return;
 356         //unsigned long flags;
 357         skb = ieee80211_get_beacon_(ieee);
 358 
 359         if (skb) {
 360                 softmac_mgmt_xmit(skb, ieee);
 361                 ieee->softmac_stats.tx_beacons++;
 362                 //dev_kfree_skb_any(skb);//edit by thomas
 363         }
 364 //      ieee->beacon_timer.expires = jiffies +
 365 //              (MSECS( ieee->current_network.beacon_interval -5));
 366 
 367         //spin_lock_irqsave(&ieee->beacon_lock,flags);
 368         if (ieee->beacon_txing && ieee->ieee_up) {
 369 //              if(!timer_pending(&ieee->beacon_timer))
 370 //                      add_timer(&ieee->beacon_timer);
 371                 mod_timer(&ieee->beacon_timer,
 372                           jiffies + msecs_to_jiffies(ieee->current_network.beacon_interval - 5));
 373         }
 374         //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
 375 }
 376 
 377 static void ieee80211_send_beacon_cb(struct timer_list *t)
 378 {
 379         struct ieee80211_device *ieee =
 380                 from_timer(ieee, t, beacon_timer);
 381         unsigned long flags;
 382 
 383         spin_lock_irqsave(&ieee->beacon_lock, flags);
 384         ieee80211_send_beacon(ieee);
 385         spin_unlock_irqrestore(&ieee->beacon_lock, flags);
 386 }
 387 
 388 static void ieee80211_send_probe(struct ieee80211_device *ieee)
 389 {
 390         struct sk_buff *skb;
 391 
 392         skb = ieee80211_probe_req(ieee);
 393         if (skb) {
 394                 softmac_mgmt_xmit(skb, ieee);
 395                 ieee->softmac_stats.tx_probe_rq++;
 396                 //dev_kfree_skb_any(skb);//edit by thomas
 397         }
 398 }
 399 
 400 static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
 401 {
 402         if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
 403                 ieee80211_send_probe(ieee);
 404                 ieee80211_send_probe(ieee);
 405         }
 406 }
 407 
 408 /* this performs syncro scan blocking the caller until all channels
 409  * in the allowed channel map has been checked.
 410  */
 411 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
 412 {
 413         short ch = 0;
 414         u8 channel_map[MAX_CHANNEL_NUMBER + 1];
 415 
 416         memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER + 1);
 417         mutex_lock(&ieee->scan_mutex);
 418 
 419         while (1) {
 420                 do {
 421                         ch++;
 422                         if (ch > MAX_CHANNEL_NUMBER)
 423                                 goto out; /* scan completed */
 424                 } while (!channel_map[ch]);
 425 
 426                 /* this function can be called in two situations
 427                  * 1- We have switched to ad-hoc mode and we are
 428                  *    performing a complete syncro scan before conclude
 429                  *    there are no interesting cell and to create a
 430                  *    new one. In this case the link state is
 431                  *    IEEE80211_NOLINK until we found an interesting cell.
 432                  *    If so the ieee8021_new_net, called by the RX path
 433                  *    will set the state to IEEE80211_LINKED, so we stop
 434                  *    scanning
 435                  * 2- We are linked and the root uses run iwlist scan.
 436                  *    So we switch to IEEE80211_LINKED_SCANNING to remember
 437                  *    that we are still logically linked (not interested in
 438                  *    new network events, despite for updating the net list,
 439                  *    but we are temporarly 'unlinked' as the driver shall
 440                  *    not filter RX frames and the channel is changing.
 441                  * So the only situation in witch are interested is to check
 442                  * if the state become LINKED because of the #1 situation
 443                  */
 444 
 445                 if (ieee->state == IEEE80211_LINKED)
 446                         goto out;
 447                 ieee->set_chan(ieee->dev, ch);
 448                 if (channel_map[ch] == 1)
 449                         ieee80211_send_probe_requests(ieee);
 450 
 451                 /* this prevent excessive time wait when we
 452                  * need to wait for a syncro scan to end..
 453                  */
 454                 if (ieee->state >= IEEE80211_LINKED && ieee->sync_scan_hurryup)
 455                         goto out;
 456 
 457                 msleep_interruptible(IEEE80211_SOFTMAC_SCAN_TIME);
 458         }
 459 out:
 460         if (ieee->state < IEEE80211_LINKED) {
 461                 ieee->actscanning = false;
 462                 mutex_unlock(&ieee->scan_mutex);
 463         } else {
 464                 ieee->sync_scan_hurryup = 0;
 465                 if (IS_DOT11D_ENABLE(ieee))
 466                         dot11d_scan_complete(ieee);
 467                 mutex_unlock(&ieee->scan_mutex);
 468         }
 469 }
 470 EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
 471 
 472 static void ieee80211_softmac_scan_wq(struct work_struct *work)
 473 {
 474         struct delayed_work *dwork = to_delayed_work(work);
 475         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
 476         static short watchdog;
 477         u8 channel_map[MAX_CHANNEL_NUMBER + 1];
 478 
 479         memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER + 1);
 480         if (!ieee->ieee_up)
 481                 return;
 482         mutex_lock(&ieee->scan_mutex);
 483         do {
 484                 ieee->current_network.channel =
 485                         (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
 486                 if (watchdog++ > MAX_CHANNEL_NUMBER) {
 487                 //if current channel is not in channel map, set to default channel.
 488                         if (!channel_map[ieee->current_network.channel]) {
 489                                 ieee->current_network.channel = 6;
 490                                 goto out; /* no good chans */
 491                         }
 492                 }
 493         } while (!channel_map[ieee->current_network.channel]);
 494         if (ieee->scanning == 0)
 495                 goto out;
 496         ieee->set_chan(ieee->dev, ieee->current_network.channel);
 497         if (channel_map[ieee->current_network.channel] == 1)
 498                 ieee80211_send_probe_requests(ieee);
 499 
 500         schedule_delayed_work(&ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
 501 
 502         mutex_unlock(&ieee->scan_mutex);
 503         return;
 504 out:
 505         if (IS_DOT11D_ENABLE(ieee))
 506                 dot11d_scan_complete(ieee);
 507         ieee->actscanning = false;
 508         watchdog = 0;
 509         ieee->scanning = 0;
 510         mutex_unlock(&ieee->scan_mutex);
 511 }
 512 
 513 static void ieee80211_beacons_start(struct ieee80211_device *ieee)
 514 {
 515         unsigned long flags;
 516         spin_lock_irqsave(&ieee->beacon_lock, flags);
 517 
 518         ieee->beacon_txing = 1;
 519         ieee80211_send_beacon(ieee);
 520 
 521         spin_unlock_irqrestore(&ieee->beacon_lock, flags);
 522 }
 523 
 524 static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
 525 {
 526         unsigned long flags;
 527 
 528         spin_lock_irqsave(&ieee->beacon_lock, flags);
 529 
 530         ieee->beacon_txing = 0;
 531         del_timer_sync(&ieee->beacon_timer);
 532 
 533         spin_unlock_irqrestore(&ieee->beacon_lock, flags);
 534 }
 535 
 536 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
 537 {
 538         if (ieee->stop_send_beacons)
 539                 ieee->stop_send_beacons(ieee->dev);
 540         if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
 541                 ieee80211_beacons_stop(ieee);
 542 }
 543 EXPORT_SYMBOL(ieee80211_stop_send_beacons);
 544 
 545 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
 546 {
 547         if (ieee->start_send_beacons)
 548                 ieee->start_send_beacons(ieee->dev, ieee->basic_rate);
 549         if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
 550                 ieee80211_beacons_start(ieee);
 551 }
 552 EXPORT_SYMBOL(ieee80211_start_send_beacons);
 553 
 554 static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
 555 {
 556 //      unsigned long flags;
 557 
 558         //ieee->sync_scan_hurryup = 1;
 559 
 560         mutex_lock(&ieee->scan_mutex);
 561 //      spin_lock_irqsave(&ieee->lock, flags);
 562 
 563         if (ieee->scanning == 1) {
 564                 ieee->scanning = 0;
 565 
 566                 cancel_delayed_work(&ieee->softmac_scan_wq);
 567         }
 568 
 569 //      spin_unlock_irqrestore(&ieee->lock, flags);
 570         mutex_unlock(&ieee->scan_mutex);
 571 }
 572 
 573 void ieee80211_stop_scan(struct ieee80211_device *ieee)
 574 {
 575         if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
 576                 ieee80211_softmac_stop_scan(ieee);
 577         else
 578                 ieee->stop_scan(ieee->dev);
 579 }
 580 EXPORT_SYMBOL(ieee80211_stop_scan);
 581 
 582 /* called with ieee->lock held */
 583 static void ieee80211_start_scan(struct ieee80211_device *ieee)
 584 {
 585         if (IS_DOT11D_ENABLE(ieee)) {
 586                 if (IS_COUNTRY_IE_VALID(ieee))
 587                         RESET_CIE_WATCHDOG(ieee);
 588         }
 589         if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
 590                 if (ieee->scanning == 0) {
 591                         ieee->scanning = 1;
 592                         schedule_delayed_work(&ieee->softmac_scan_wq, 0);
 593                 }
 594         } else {
 595                 ieee->start_scan(ieee->dev);
 596         }
 597 }
 598 
 599 /* called with wx_mutex held */
 600 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
 601 {
 602         if (IS_DOT11D_ENABLE(ieee)) {
 603                 if (IS_COUNTRY_IE_VALID(ieee))
 604                         RESET_CIE_WATCHDOG(ieee);
 605         }
 606         ieee->sync_scan_hurryup = 0;
 607         if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
 608                 ieee80211_softmac_scan_syncro(ieee);
 609         else
 610                 ieee->scan_syncro(ieee->dev);
 611 }
 612 EXPORT_SYMBOL(ieee80211_start_scan_syncro);
 613 
 614 static inline struct sk_buff *
 615 ieee80211_authentication_req(struct ieee80211_network *beacon,
 616                              struct ieee80211_device *ieee, int challengelen)
 617 {
 618         struct sk_buff *skb;
 619         struct ieee80211_authentication *auth;
 620         int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
 621 
 622         skb = dev_alloc_skb(len);
 623         if (!skb)
 624                 return NULL;
 625 
 626         skb_reserve(skb, ieee->tx_headroom);
 627         auth = skb_put(skb, sizeof(struct ieee80211_authentication));
 628 
 629         if (challengelen)
 630                 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH
 631                                                      | IEEE80211_FCTL_WEP);
 632         else
 633                 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
 634 
 635         auth->header.duration_id = cpu_to_le16(0x013a);
 636 
 637         memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
 638         memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 639         memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
 640 
 641         //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
 642         if (ieee->auth_mode == 0)
 643                 auth->algorithm = WLAN_AUTH_OPEN;
 644         else if (ieee->auth_mode == 1)
 645                 auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY);
 646         else if (ieee->auth_mode == 2)
 647                 auth->algorithm = WLAN_AUTH_OPEN; /* 0x80; */
 648         printk("=================>%s():auth->algorithm is %d\n", __func__, auth->algorithm);
 649         auth->transaction = cpu_to_le16(ieee->associate_seq);
 650         ieee->associate_seq++;
 651 
 652         auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
 653 
 654         return skb;
 655 }
 656 
 657 static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
 658 {
 659         u8 *tag;
 660         int beacon_size;
 661         struct ieee80211_probe_response *beacon_buf;
 662         struct sk_buff *skb = NULL;
 663         int encrypt;
 664         int atim_len, erp_len;
 665         struct ieee80211_crypt_data *crypt;
 666 
 667         char *ssid = ieee->current_network.ssid;
 668         int ssid_len = ieee->current_network.ssid_len;
 669         int rate_len = ieee->current_network.rates_len + 2;
 670         int rate_ex_len = ieee->current_network.rates_ex_len;
 671         int wpa_ie_len = ieee->wpa_ie_len;
 672         u8 erpinfo_content = 0;
 673 
 674         u8 *tmp_ht_cap_buf;
 675         u8 tmp_ht_cap_len = 0;
 676         u8 *tmp_ht_info_buf;
 677         u8 tmp_ht_info_len = 0;
 678         PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
 679         u8 *tmp_generic_ie_buf = NULL;
 680         u8 tmp_generic_ie_len = 0;
 681 
 682         if (rate_ex_len > 0)
 683                 rate_ex_len += 2;
 684 
 685         if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
 686                 atim_len = 4;
 687         else
 688                 atim_len = 0;
 689 
 690         if (ieee80211_is_54g(&ieee->current_network))
 691                 erp_len = 3;
 692         else
 693                 erp_len = 0;
 694 
 695         crypt = ieee->crypt[ieee->tx_keyidx];
 696 
 697         encrypt = ieee->host_encrypt && crypt && crypt->ops &&
 698                 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
 699         /* HT ralated element */
 700         tmp_ht_cap_buf = (u8 *)&ieee->pHTInfo->SelfHTCap;
 701         tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
 702         tmp_ht_info_buf = (u8 *)&ieee->pHTInfo->SelfHTInfo;
 703         tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
 704         HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len, encrypt);
 705         HTConstructInfoElement(ieee, tmp_ht_info_buf, &tmp_ht_info_len, encrypt);
 706 
 707         if (pHTInfo->bRegRT2RTAggregation) {
 708                 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
 709                 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
 710                 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
 711         }
 712 //      printk("===============>tmp_ht_cap_len is %d,tmp_ht_info_len is %d, tmp_generic_ie_len is %d\n",tmp_ht_cap_len,tmp_ht_info_len,tmp_generic_ie_len);
 713         beacon_size = sizeof(struct ieee80211_probe_response) + 2
 714                 + ssid_len
 715                 + 3 //channel
 716                 + rate_len
 717                 + rate_ex_len
 718                 + atim_len
 719                 + erp_len
 720                 + wpa_ie_len
 721         //      + tmp_ht_cap_len
 722         //      + tmp_ht_info_len
 723         //      + tmp_generic_ie_len
 724 //              + wmm_len+2
 725                 + ieee->tx_headroom;
 726         skb = dev_alloc_skb(beacon_size);
 727         if (!skb)
 728                 return NULL;
 729         skb_reserve(skb, ieee->tx_headroom);
 730         beacon_buf = skb_put(skb, (beacon_size - ieee->tx_headroom));
 731         memcpy(beacon_buf->header.addr1, dest, ETH_ALEN);
 732         memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 733         memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
 734 
 735         beacon_buf->header.duration_id = 0; /* FIXME */
 736         beacon_buf->beacon_interval =
 737                 cpu_to_le16(ieee->current_network.beacon_interval);
 738         beacon_buf->capability =
 739                 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
 740         beacon_buf->capability |=
 741                 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); /* add short preamble here */
 742 
 743         if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
 744                 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
 745 
 746         if (encrypt)
 747                 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
 748 
 749         beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
 750         beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
 751         beacon_buf->info_element[0].len = ssid_len;
 752 
 753         tag = (u8 *)beacon_buf->info_element[0].data;
 754 
 755         memcpy(tag, ssid, ssid_len);
 756 
 757         tag += ssid_len;
 758 
 759         *(tag++) = MFIE_TYPE_RATES;
 760         *(tag++) = rate_len - 2;
 761         memcpy(tag, ieee->current_network.rates, rate_len - 2);
 762         tag += rate_len - 2;
 763 
 764         *(tag++) = MFIE_TYPE_DS_SET;
 765         *(tag++) = 1;
 766         *(tag++) = ieee->current_network.channel;
 767 
 768         if (atim_len) {
 769                 *(tag++) = MFIE_TYPE_IBSS_SET;
 770                 *(tag++) = 2;
 771 
 772                 put_unaligned_le16(ieee->current_network.atim_window,
 773                                    tag);
 774                 tag += 2;
 775         }
 776 
 777         if (erp_len) {
 778                 *(tag++) = MFIE_TYPE_ERP;
 779                 *(tag++) = 1;
 780                 *(tag++) = erpinfo_content;
 781         }
 782         if (rate_ex_len) {
 783                 *(tag++) = MFIE_TYPE_RATES_EX;
 784                 *(tag++) = rate_ex_len - 2;
 785                 memcpy(tag, ieee->current_network.rates_ex, rate_ex_len - 2);
 786                 tag += rate_ex_len - 2;
 787         }
 788 
 789         if (wpa_ie_len) {
 790                 if (ieee->iw_mode == IW_MODE_ADHOC) {
 791                         //as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07
 792                         memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
 793                 }
 794                 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
 795                 tag += wpa_ie_len;
 796         }
 797 
 798         //skb->dev = ieee->dev;
 799         return skb;
 800 }
 801 
 802 static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
 803                                             u8 *dest)
 804 {
 805         struct sk_buff *skb;
 806         u8 *tag;
 807 
 808         struct ieee80211_crypt_data *crypt;
 809         struct ieee80211_assoc_response_frame *assoc;
 810         short encrypt;
 811 
 812         unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
 813         int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
 814 
 815         skb = dev_alloc_skb(len);
 816 
 817         if (!skb)
 818                 return NULL;
 819 
 820         skb_reserve(skb, ieee->tx_headroom);
 821 
 822         assoc = skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
 823 
 824         assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
 825         memcpy(assoc->header.addr1, dest, ETH_ALEN);
 826         memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
 827         memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 828         assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
 829                 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
 830 
 831         if (ieee->short_slot)
 832                 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
 833 
 834         if (ieee->host_encrypt)
 835                 crypt = ieee->crypt[ieee->tx_keyidx];
 836         else
 837                 crypt = NULL;
 838 
 839         encrypt = crypt && crypt->ops;
 840 
 841         if (encrypt)
 842                 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
 843 
 844         assoc->status = 0;
 845         assoc->aid = cpu_to_le16(ieee->assoc_id);
 846         if (ieee->assoc_id == 0x2007)
 847                 ieee->assoc_id = 0;
 848         else
 849                 ieee->assoc_id++;
 850 
 851         tag = skb_put(skb, rate_len);
 852 
 853         ieee80211_MFIE_Brate(ieee, &tag);
 854         ieee80211_MFIE_Grate(ieee, &tag);
 855 
 856         return skb;
 857 }
 858 
 859 static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
 860                                            int status, u8 *dest)
 861 {
 862         struct sk_buff *skb;
 863         struct ieee80211_authentication *auth;
 864         int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication) + 1;
 865 
 866         skb = dev_alloc_skb(len);
 867 
 868         if (!skb)
 869                 return NULL;
 870 
 871         skb->len = sizeof(struct ieee80211_authentication);
 872 
 873         auth = (struct ieee80211_authentication *)skb->data;
 874 
 875         auth->status = cpu_to_le16(status);
 876         auth->transaction = cpu_to_le16(2);
 877         auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
 878 
 879         memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
 880         memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 881         memcpy(auth->header.addr1, dest, ETH_ALEN);
 882         auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
 883         return skb;
 884 }
 885 
 886 static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
 887                                            short pwr)
 888 {
 889         struct sk_buff *skb;
 890         struct rtl_80211_hdr_3addr *hdr;
 891 
 892         skb = dev_alloc_skb(sizeof(struct rtl_80211_hdr_3addr));
 893 
 894         if (!skb)
 895                 return NULL;
 896 
 897         hdr = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
 898 
 899         memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
 900         memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
 901         memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
 902 
 903         hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
 904                                      IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
 905                                      (pwr ? IEEE80211_FCTL_PM : 0));
 906 
 907         return skb;
 908 }
 909 
 910 static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
 911 {
 912         struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
 913 
 914         if (buf)
 915                 softmac_mgmt_xmit(buf, ieee);
 916 }
 917 
 918 static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
 919                                    u8 *dest)
 920 {
 921         struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
 922 
 923         if (buf)
 924                 softmac_mgmt_xmit(buf, ieee);
 925 }
 926 
 927 static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
 928 {
 929         struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
 930         if (buf)
 931                 softmac_mgmt_xmit(buf, ieee);
 932 }
 933 
 934 static inline struct sk_buff *
 935 ieee80211_association_req(struct ieee80211_network *beacon,
 936                           struct ieee80211_device *ieee)
 937 {
 938         struct sk_buff *skb;
 939         //unsigned long flags;
 940 
 941         struct ieee80211_assoc_request_frame *hdr;
 942         u8 *tag;//,*rsn_ie;
 943         //short info_addr = 0;
 944         //int i;
 945         //u16 suite_count = 0;
 946         //u8 suit_select = 0;
 947         //unsigned int wpa_len = beacon->wpa_ie_len;
 948         //for HT
 949         u8 *ht_cap_buf = NULL;
 950         u8 ht_cap_len = 0;
 951         u8 *realtek_ie_buf = NULL;
 952         u8 realtek_ie_len = 0;
 953         int wpa_ie_len = ieee->wpa_ie_len;
 954         unsigned int ckip_ie_len = 0;
 955         unsigned int ccxrm_ie_len = 0;
 956         unsigned int cxvernum_ie_len = 0;
 957         struct ieee80211_crypt_data *crypt;
 958         int encrypt;
 959 
 960         unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
 961         unsigned int wmm_info_len = beacon->qos_data.supported ? 9 : 0;
 962 #ifdef THOMAS_TURBO
 963         unsigned int turbo_info_len = beacon->Turbo_Enable ? 9 : 0;
 964 #endif
 965 
 966         int len = 0;
 967 
 968         crypt = ieee->crypt[ieee->tx_keyidx];
 969         encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
 970 
 971         /* Include High Throuput capability && Realtek proprietary */
 972         if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
 973                 ht_cap_buf = (u8 *)&ieee->pHTInfo->SelfHTCap;
 974                 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
 975                 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
 976                 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
 977                         realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
 978                         realtek_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
 979                         HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
 980                 }
 981         }
 982         if (ieee->qos_support)
 983                 wmm_info_len = beacon->qos_data.supported ? 9 : 0;
 984 
 985         if (beacon->bCkipSupported)
 986                 ckip_ie_len = 30 + 2;
 987 
 988         if (beacon->bCcxRmEnable)
 989                 ccxrm_ie_len = 6 + 2;
 990 
 991         if (beacon->BssCcxVerNumber >= 2)
 992                 cxvernum_ie_len = 5 + 2;
 993 
 994 #ifdef THOMAS_TURBO
 995         len = sizeof(struct ieee80211_assoc_request_frame) + 2
 996                 + beacon->ssid_len      /* essid tagged val */
 997                 + rate_len      /* rates tagged val */
 998                 + wpa_ie_len
 999                 + wmm_info_len
1000                 + turbo_info_len
1001                 + ht_cap_len
1002                 + realtek_ie_len
1003                 + ckip_ie_len
1004                 + ccxrm_ie_len
1005                 + cxvernum_ie_len
1006                 + ieee->tx_headroom;
1007 #else
1008         len = sizeof(struct ieee80211_assoc_request_frame) + 2
1009                 + beacon->ssid_len      /* essid tagged val */
1010                 + rate_len      /* rates tagged val */
1011                 + wpa_ie_len
1012                 + wmm_info_len
1013                 + ht_cap_len
1014                 + realtek_ie_len
1015                 + ckip_ie_len
1016                 + ccxrm_ie_len
1017                 + cxvernum_ie_len
1018                 + ieee->tx_headroom;
1019 #endif
1020         skb = dev_alloc_skb(len);
1021 
1022         if (!skb)
1023                 return NULL;
1024 
1025         skb_reserve(skb, ieee->tx_headroom);
1026 
1027         hdr = skb_put(skb, sizeof(struct ieee80211_assoc_request_frame) + 2);
1028 
1029         hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1030         hdr->header.duration_id = cpu_to_le16(37);
1031         memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1032         memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1033         memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1034 
1035         memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1036 
1037         hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1038         if (beacon->capability & WLAN_CAPABILITY_PRIVACY)
1039                 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1040 
1041         if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1042                 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1043 
1044         if (ieee->short_slot)
1045                 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1046         if (wmm_info_len) //QOS
1047                 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1048 
1049         hdr->listen_interval = cpu_to_le16(0xa);
1050 
1051         hdr->info_element[0].id = MFIE_TYPE_SSID;
1052 
1053         hdr->info_element[0].len = beacon->ssid_len;
1054         skb_put_data(skb, beacon->ssid, beacon->ssid_len);
1055 
1056         tag = skb_put(skb, rate_len);
1057 
1058         ieee80211_MFIE_Brate(ieee, &tag);
1059         ieee80211_MFIE_Grate(ieee, &tag);
1060         // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1061         if (beacon->bCkipSupported) {
1062                 static u8       AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1063                 u8      CcxAironetBuf[30];
1064                 struct octet_string     osCcxAironetIE;
1065 
1066                 memset(CcxAironetBuf, 0, 30);
1067                 osCcxAironetIE.octet = CcxAironetBuf;
1068                 osCcxAironetIE.length = sizeof(CcxAironetBuf);
1069                 //
1070                 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1071                 // We want to make the device type as "4500-client". 060926, by CCW.
1072                 //
1073                 memcpy(osCcxAironetIE.octet, AironetIeOui, sizeof(AironetIeOui));
1074 
1075                 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1076                 // "The CKIP negotiation is started with the associate request from the client to the access point,
1077                 //  containing an Aironet element with both the MIC and KP bits set."
1078                 osCcxAironetIE.octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK | SUPPORT_CKIP_MIC);
1079                 tag = skb_put(skb, ckip_ie_len);
1080                 *tag++ = MFIE_TYPE_AIRONET;
1081                 *tag++ = osCcxAironetIE.length;
1082                 memcpy(tag, osCcxAironetIE.octet, osCcxAironetIE.length);
1083                 tag += osCcxAironetIE.length;
1084         }
1085 
1086         if (beacon->bCcxRmEnable) {
1087                 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1088                 struct octet_string osCcxRmCap;
1089 
1090                 osCcxRmCap.octet = CcxRmCapBuf;
1091                 osCcxRmCap.length = sizeof(CcxRmCapBuf);
1092                 tag = skb_put(skb, ccxrm_ie_len);
1093                 *tag++ = MFIE_TYPE_GENERIC;
1094                 *tag++ = osCcxRmCap.length;
1095                 memcpy(tag, osCcxRmCap.octet, osCcxRmCap.length);
1096                 tag += osCcxRmCap.length;
1097         }
1098 
1099         if (beacon->BssCcxVerNumber >= 2) {
1100                 u8                      CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1101                 struct octet_string     osCcxVerNum;
1102                 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1103                 osCcxVerNum.octet = CcxVerNumBuf;
1104                 osCcxVerNum.length = sizeof(CcxVerNumBuf);
1105                 tag = skb_put(skb, cxvernum_ie_len);
1106                 *tag++ = MFIE_TYPE_GENERIC;
1107                 *tag++ = osCcxVerNum.length;
1108                 memcpy(tag, osCcxVerNum.octet, osCcxVerNum.length);
1109                 tag += osCcxVerNum.length;
1110         }
1111         //HT cap element
1112         if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1113                 if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) {
1114                         tag = skb_put(skb, ht_cap_len);
1115                         *tag++ = MFIE_TYPE_HT_CAP;
1116                         *tag++ = ht_cap_len - 2;
1117                         memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1118                         tag += ht_cap_len - 2;
1119                 }
1120         }
1121 
1122         //choose what wpa_supplicant gives to associate.
1123         if (wpa_ie_len)
1124                 skb_put_data(skb, ieee->wpa_ie, wpa_ie_len);
1125 
1126         if (wmm_info_len) {
1127                 tag = skb_put(skb, wmm_info_len);
1128                 ieee80211_WMM_Info(ieee, &tag);
1129         }
1130 #ifdef THOMAS_TURBO
1131         if (turbo_info_len) {
1132                 tag = skb_put(skb, turbo_info_len);
1133                 ieee80211_TURBO_Info(ieee, &tag);
1134         }
1135 #endif
1136 
1137         if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1138                 if (ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) {
1139                         tag = skb_put(skb, ht_cap_len);
1140                         *tag++ = MFIE_TYPE_GENERIC;
1141                         *tag++ = ht_cap_len - 2;
1142                         memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1143                         tag += ht_cap_len - 2;
1144                 }
1145 
1146                 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
1147                         tag = skb_put(skb, realtek_ie_len);
1148                         *tag++ = MFIE_TYPE_GENERIC;
1149                         *tag++ = realtek_ie_len - 2;
1150                         memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
1151                 }
1152         }
1153 //      printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
1154 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1155         return skb;
1156 }
1157 
1158 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1159 {
1160         unsigned long flags;
1161         spin_lock_irqsave(&ieee->lock, flags);
1162 
1163         ieee->associate_seq++;
1164 
1165         /* don't scan, and avoid to have the RX path possibily
1166          * try again to associate. Even do not react to AUTH or
1167          * ASSOC response. Just wait for the retry wq to be scheduled.
1168          * Here we will check if there are good nets to associate
1169          * with, so we retry or just get back to NO_LINK and scanning
1170          */
1171         if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) {
1172                 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1173                 ieee->softmac_stats.no_auth_rs++;
1174         } else {
1175                 IEEE80211_DEBUG_MGMT("Association failed\n");
1176                 ieee->softmac_stats.no_ass_rs++;
1177         }
1178 
1179         ieee->state = IEEE80211_ASSOCIATING_RETRY;
1180 
1181         schedule_delayed_work(&ieee->associate_retry_wq, \
1182                               IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1183 
1184         spin_unlock_irqrestore(&ieee->lock, flags);
1185 }
1186 
1187 static void ieee80211_associate_abort_cb(struct timer_list *t)
1188 {
1189         struct ieee80211_device *dev = from_timer(dev, t, associate_timer);
1190 
1191         ieee80211_associate_abort(dev);
1192 }
1193 
1194 static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1195 {
1196         struct ieee80211_network *beacon = &ieee->current_network;
1197         struct sk_buff *skb;
1198 
1199         IEEE80211_DEBUG_MGMT("Stopping scan\n");
1200 
1201         ieee->softmac_stats.tx_auth_rq++;
1202         skb = ieee80211_authentication_req(beacon, ieee, 0);
1203 
1204         if (!skb) {
1205                 ieee80211_associate_abort(ieee);
1206         } else {
1207                 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING;
1208                 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1209                 softmac_mgmt_xmit(skb, ieee);
1210                 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1211                 if (!timer_pending(&ieee->associate_timer)) {
1212                         ieee->associate_timer.expires = jiffies + (HZ / 2);
1213                         add_timer(&ieee->associate_timer);
1214                 }
1215                 //dev_kfree_skb_any(skb);//edit by thomas
1216         }
1217 }
1218 
1219 static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1220                                      u8 *challenge,
1221                                      int chlen)
1222 {
1223         u8 *c;
1224         struct sk_buff *skb;
1225         struct ieee80211_network *beacon = &ieee->current_network;
1226 //      int hlen = sizeof(struct ieee80211_authentication);
1227 
1228         ieee->associate_seq++;
1229         ieee->softmac_stats.tx_auth_rq++;
1230 
1231         skb = ieee80211_authentication_req(beacon, ieee, chlen + 2);
1232         if (!skb) {
1233                 ieee80211_associate_abort(ieee);
1234         } else {
1235                 c = skb_put(skb, chlen + 2);
1236                 *(c++) = MFIE_TYPE_CHALLENGE;
1237                 *(c++) = chlen;
1238                 memcpy(c, challenge, chlen);
1239 
1240                 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1241 
1242                 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct rtl_80211_hdr_3addr));
1243 
1244                 softmac_mgmt_xmit(skb, ieee);
1245                 mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
1246                 //dev_kfree_skb_any(skb);//edit by thomas
1247         }
1248         kfree(challenge);
1249 }
1250 
1251 static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1252 {
1253         struct sk_buff *skb;
1254         struct ieee80211_network *beacon = &ieee->current_network;
1255 
1256         del_timer_sync(&ieee->associate_timer);
1257 
1258         IEEE80211_DEBUG_MGMT("Sending association request\n");
1259 
1260         ieee->softmac_stats.tx_ass_rq++;
1261         skb = ieee80211_association_req(beacon, ieee);
1262         if (!skb) {
1263                 ieee80211_associate_abort(ieee);
1264         } else {
1265                 softmac_mgmt_xmit(skb, ieee);
1266                 mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
1267                 //dev_kfree_skb_any(skb);//edit by thomas
1268         }
1269 }
1270 static void ieee80211_associate_complete_wq(struct work_struct *work)
1271 {
1272         struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1273         printk(KERN_INFO "Associated successfully\n");
1274         if (ieee80211_is_54g(&ieee->current_network) &&
1275             (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
1276                 ieee->rate = 108;
1277                 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1278         } else {
1279                 ieee->rate = 22;
1280                 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1281         }
1282         if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1283                 printk("Successfully associated, ht enabled\n");
1284                 HTOnAssocRsp(ieee);
1285         } else {
1286                 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1287                 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1288                 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1289         }
1290         ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval / 500);
1291         // To prevent the immediately calling watch_dog after association.
1292         if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
1293                 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1294                 ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
1295         }
1296         ieee->link_change(ieee->dev);
1297         if (!ieee->is_silent_reset) {
1298                 printk("============>normal associate\n");
1299                 notify_wx_assoc_event(ieee);
1300         } else {
1301                 printk("==================>silent reset associate\n");
1302                 ieee->is_silent_reset = false;
1303         }
1304 
1305         if (ieee->data_hard_resume)
1306                 ieee->data_hard_resume(ieee->dev);
1307         netif_carrier_on(ieee->dev);
1308 }
1309 
1310 static void ieee80211_associate_complete(struct ieee80211_device *ieee)
1311 {
1312 //      int i;
1313 //      struct net_device* dev = ieee->dev;
1314         del_timer_sync(&ieee->associate_timer);
1315 
1316         ieee->state = IEEE80211_LINKED;
1317         //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1318         schedule_work(&ieee->associate_complete_wq);
1319 }
1320 
1321 static void ieee80211_associate_procedure_wq(struct work_struct *work)
1322 {
1323         struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1324         ieee->sync_scan_hurryup = 1;
1325         mutex_lock(&ieee->wx_mutex);
1326 
1327         if (ieee->data_hard_stop)
1328                 ieee->data_hard_stop(ieee->dev);
1329 
1330         ieee80211_stop_scan(ieee);
1331         printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
1332         //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1333         HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1334 
1335         ieee->associate_seq = 1;
1336         ieee80211_associate_step1(ieee);
1337 
1338         mutex_unlock(&ieee->wx_mutex);
1339 }
1340 
1341 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1342 {
1343         u8 tmp_ssid[IW_ESSID_MAX_SIZE + 1];
1344         int tmp_ssid_len = 0;
1345 
1346         short apset, ssidset, ssidbroad, apmatch, ssidmatch;
1347 
1348         /* we are interested in new new only if we are not associated
1349          * and we are not associating / authenticating
1350          */
1351         if (ieee->state != IEEE80211_NOLINK)
1352                 return;
1353 
1354         if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1355                 return;
1356 
1357         if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1358                 return;
1359 
1360         if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
1361                 /* if the user specified the AP MAC, we need also the essid
1362                  * This could be obtained by beacons or, if the network does not
1363                  * broadcast it, it can be put manually.
1364                  */
1365                 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1366                 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1367                 ssidbroad =  !(net->ssid_len == 0 || net->ssid[0] == '\0');
1368                 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN) == 0);
1369                 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len) &&
1370                         (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1371 
1372                 /* if the user set the AP check if match.
1373                  * if the network does not broadcast essid we check the user supplyed ANY essid
1374                  * if the network does broadcast and the user does not set essid it is OK
1375                  * if the network does broadcast and the user did set essid chech if essid match
1376                  */
1377                 if ((apset && apmatch &&
1378                      ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
1379                     /* if the ap is not set, check that the user set the bssid
1380                      * and the network does broadcast and that those two bssid matches
1381                      */
1382                     (!apset && ssidset && ssidbroad && ssidmatch)) {
1383                         /* if the essid is hidden replace it with the
1384                          * essid provided by the user.
1385                          */
1386                         if (!ssidbroad) {
1387                                 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1388                                 tmp_ssid_len = ieee->current_network.ssid_len;
1389                         }
1390                         memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1391 
1392                         strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1393                         ieee->current_network.ssid_len = tmp_ssid_len;
1394                         printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",
1395                                ieee->current_network.ssid,
1396                                ieee->current_network.channel,
1397                                ieee->current_network.qos_data.supported,
1398                                ieee->pHTInfo->bEnableHT,
1399                                ieee->current_network.bssht.bdSupportHT);
1400 
1401                         //ieee->pHTInfo->IOTAction = 0;
1402                         HTResetIOTSetting(ieee->pHTInfo);
1403                         if (ieee->iw_mode == IW_MODE_INFRA) {
1404                                 /* Join the network for the first time */
1405                                 ieee->AsocRetryCount = 0;
1406                                 //for HT by amy 080514
1407                                 if ((ieee->current_network.qos_data.supported == 1) &&
1408                                     // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1409                                     ieee->current_network.bssht.bdSupportHT) {
1410 /*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
1411                                         //      ieee->pHTInfo->bCurrentHTSupport = true;
1412                                         HTResetSelfAndSavePeerSetting(ieee, &ieee->current_network);
1413                                 } else {
1414                                         ieee->pHTInfo->bCurrentHTSupport = false;
1415                                 }
1416 
1417                                 ieee->state = IEEE80211_ASSOCIATING;
1418                                 schedule_work(&ieee->associate_procedure_wq);
1419                         } else {
1420                                 if (ieee80211_is_54g(&ieee->current_network) &&
1421                                     (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
1422                                         ieee->rate = 108;
1423                                         ieee->SetWirelessMode(ieee->dev, IEEE_G);
1424                                         printk(KERN_INFO"Using G rates\n");
1425                                 } else {
1426                                         ieee->rate = 22;
1427                                         ieee->SetWirelessMode(ieee->dev, IEEE_B);
1428                                         printk(KERN_INFO"Using B rates\n");
1429                                 }
1430                                 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1431                                 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1432                                 ieee->state = IEEE80211_LINKED;
1433                         }
1434                 }
1435         }
1436 }
1437 
1438 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1439 {
1440         unsigned long flags;
1441         struct ieee80211_network *target;
1442 
1443         spin_lock_irqsave(&ieee->lock, flags);
1444 
1445         list_for_each_entry(target, &ieee->network_list, list) {
1446                 /* if the state become different that NOLINK means
1447                  * we had found what we are searching for
1448                  */
1449 
1450                 if (ieee->state != IEEE80211_NOLINK)
1451                         break;
1452 
1453                 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1454                         ieee80211_softmac_new_net(ieee, target);
1455         }
1456 
1457         spin_unlock_irqrestore(&ieee->lock, flags);
1458 }
1459 
1460 static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1461 {
1462         struct ieee80211_authentication *a;
1463         u8 *t;
1464         if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1465                 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1466                 return 0xcafe;
1467         }
1468         *challenge = NULL;
1469         a = (struct ieee80211_authentication *)skb->data;
1470         if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
1471                 t = skb->data + sizeof(struct ieee80211_authentication);
1472 
1473                 if (*(t++) == MFIE_TYPE_CHALLENGE) {
1474                         *chlen = *(t++);
1475                         *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1476                         if (!*challenge)
1477                                 return -ENOMEM;
1478                 }
1479         }
1480 
1481         return le16_to_cpu(a->status);
1482 }
1483 
1484 static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1485 {
1486         struct ieee80211_authentication *a;
1487 
1488         if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1489                 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len);
1490                 return -1;
1491         }
1492         a = (struct ieee80211_authentication *)skb->data;
1493 
1494         memcpy(dest, a->header.addr2, ETH_ALEN);
1495 
1496         if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1497                 return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1498 
1499         return WLAN_STATUS_SUCCESS;
1500 }
1501 
1502 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1503 {
1504         u8 *tag;
1505         u8 *skbend;
1506         u8 *ssid = NULL;
1507         u8 ssidlen = 0;
1508 
1509         struct rtl_80211_hdr_3addr   *header =
1510                 (struct rtl_80211_hdr_3addr   *)skb->data;
1511 
1512         if (skb->len < sizeof(struct rtl_80211_hdr_3addr))
1513                 return -1; /* corrupted */
1514 
1515         memcpy(src, header->addr2, ETH_ALEN);
1516 
1517         skbend = (u8 *)skb->data + skb->len;
1518 
1519         tag = skb->data + sizeof(struct rtl_80211_hdr_3addr);
1520 
1521         while (tag + 1 < skbend) {
1522                 if (*tag == 0) {
1523                         ssid = tag + 2;
1524                         ssidlen = *(tag + 1);
1525                         break;
1526                 }
1527                 tag++; /* point to the len field */
1528                 tag = tag + *(tag); /* point to the last data byte of the tag */
1529                 tag++; /* point to the next tag */
1530         }
1531 
1532         //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1533         if (ssidlen == 0)
1534                 return 1;
1535 
1536         if (!ssid)
1537                 return 1; /* ssid not found in tagged param */
1538 
1539         return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1540 }
1541 
1542 static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1543 {
1544         struct ieee80211_assoc_request_frame *a;
1545 
1546         if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1547                 sizeof(struct ieee80211_info_element))) {
1548                 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1549                 return -1;
1550         }
1551 
1552         a = (struct ieee80211_assoc_request_frame *)skb->data;
1553 
1554         memcpy(dest, a->header.addr2, ETH_ALEN);
1555 
1556         return 0;
1557 }
1558 
1559 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1560 {
1561         struct ieee80211_assoc_response_frame *response_head;
1562         u16 status_code;
1563 
1564         if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
1565                 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1566                 return 0xcafe;
1567         }
1568 
1569         response_head = (struct ieee80211_assoc_response_frame *)skb->data;
1570         *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1571 
1572         status_code = le16_to_cpu(response_head->status);
1573         if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES ||
1574              status_code == WLAN_STATUS_CAPS_UNSUPPORTED) &&
1575             ((ieee->mode == IEEE_G) &&
1576              (ieee->current_network.mode == IEEE_N_24G) &&
1577              (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT - 1)))) {
1578                 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1579         } else {
1580                 ieee->AsocRetryCount = 0;
1581         }
1582 
1583         return le16_to_cpu(response_head->status);
1584 }
1585 
1586 static inline void
1587 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1588 {
1589         u8 dest[ETH_ALEN];
1590 
1591         //IEEE80211DMESG("Rx probe");
1592         ieee->softmac_stats.rx_probe_rq++;
1593         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1594         if (probe_rq_parse(ieee, skb, dest)) {
1595                 //IEEE80211DMESG("Was for me!");
1596                 ieee->softmac_stats.tx_probe_rs++;
1597                 ieee80211_resp_to_probe(ieee, dest);
1598         }
1599 }
1600 
1601 static inline void
1602 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1603 {
1604         u8 dest[ETH_ALEN];
1605         int status;
1606         //IEEE80211DMESG("Rx probe");
1607         ieee->softmac_stats.rx_auth_rq++;
1608 
1609         status = auth_rq_parse(skb, dest);
1610         if (status != -1)
1611                 ieee80211_resp_to_auth(ieee, status, dest);
1612         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1613 }
1614 
1615 static inline void
1616 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1617 {
1618         u8 dest[ETH_ALEN];
1619         //unsigned long flags;
1620 
1621         ieee->softmac_stats.rx_ass_rq++;
1622         if (assoc_rq_parse(skb, dest) != -1)
1623                 ieee80211_resp_to_assoc_rq(ieee, dest);
1624 
1625         printk(KERN_INFO"New client associated: %pM\n", dest);
1626         //FIXME
1627 }
1628 
1629 static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1630                                              short pwr)
1631 {
1632         struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1633 
1634         if (buf)
1635                 softmac_ps_mgmt_xmit(buf, ieee);
1636 }
1637 /* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
1638 
1639 static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1640                                     u32 *time_l)
1641 {
1642         int timeout;
1643         u8 dtim;
1644         /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1645                 ieee->iw_mode != IW_MODE_INFRA ||
1646                 ieee->state != IEEE80211_LINKED)
1647 
1648                 return 0;
1649         */
1650         dtim = ieee->current_network.dtim_data;
1651         if (!(dtim & IEEE80211_DTIM_VALID))
1652                 return 0;
1653         timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1654         ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1655 
1656         if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps))
1657                 return 2;
1658 
1659         if (!time_after(jiffies,
1660                         dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout)))
1661                 return 0;
1662 
1663         if (!time_after(jiffies,
1664                         ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
1665                 return 0;
1666 
1667         if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
1668             (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1669                 return 0;
1670 
1671         if (time_l) {
1672                 *time_l = ieee->current_network.last_dtim_sta_time[0]
1673                         + (ieee->current_network.beacon_interval
1674                            * ieee->current_network.dtim_period) * 1000;
1675         }
1676 
1677         if (time_h) {
1678                 *time_h = ieee->current_network.last_dtim_sta_time[1];
1679                 if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1680                         *time_h += 1;
1681         }
1682 
1683         return 1;
1684 }
1685 
1686 static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1687 {
1688         u32 th, tl;
1689         short sleep;
1690 
1691         unsigned long flags, flags2;
1692 
1693         spin_lock_irqsave(&ieee->lock, flags);
1694 
1695         if ((ieee->ps == IEEE80211_PS_DISABLED ||
1696              ieee->iw_mode != IW_MODE_INFRA ||
1697              ieee->state != IEEE80211_LINKED)) {
1698                 //      #warning CHECK_LOCK_HERE
1699                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1700 
1701                 ieee80211_sta_wakeup(ieee, 1);
1702 
1703                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1704         }
1705 
1706         sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl);
1707         /* 2 wake, 1 sleep, 0 do nothing */
1708         if (sleep == 0)
1709                 goto out;
1710 
1711         if (sleep == 1) {
1712                 if (ieee->sta_sleep == 1) {
1713                         ieee->enter_sleep_state(ieee->dev, th, tl);
1714                 } else if (ieee->sta_sleep == 0) {
1715                 //      printk("send null 1\n");
1716                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1717 
1718                         if (ieee->ps_is_queue_empty(ieee->dev)) {
1719                                 ieee->sta_sleep = 2;
1720 
1721                                 ieee->ps_request_tx_ack(ieee->dev);
1722 
1723                                 ieee80211_sta_ps_send_null_frame(ieee, 1);
1724 
1725                                 ieee->ps_th = th;
1726                                 ieee->ps_tl = tl;
1727                         }
1728                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1729                 }
1730         } else if (sleep == 2) {
1731 //#warning CHECK_LOCK_HERE
1732                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1733 
1734                 ieee80211_sta_wakeup(ieee, 1);
1735 
1736                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1737         }
1738 out:
1739         spin_unlock_irqrestore(&ieee->lock, flags);
1740 }
1741 
1742 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1743 {
1744         if (ieee->sta_sleep == 0) {
1745                 if (nl) {
1746                         printk("Warning: driver is probably failing to report TX ps error\n");
1747                         ieee->ps_request_tx_ack(ieee->dev);
1748                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1749                 }
1750                 return;
1751         }
1752 
1753         if (ieee->sta_sleep == 1)
1754                 ieee->sta_wake_up(ieee->dev);
1755 
1756         ieee->sta_sleep = 0;
1757 
1758         if (nl) {
1759                 ieee->ps_request_tx_ack(ieee->dev);
1760                 ieee80211_sta_ps_send_null_frame(ieee, 0);
1761         }
1762 }
1763 
1764 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1765 {
1766         unsigned long flags, flags2;
1767 
1768         spin_lock_irqsave(&ieee->lock, flags);
1769 
1770         if (ieee->sta_sleep == 2) {
1771                 /* Null frame with PS bit set */
1772                 if (success) {
1773                         ieee->sta_sleep = 1;
1774                         ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl);
1775                 }
1776                 /* if the card report not success we can't be sure the AP
1777                  * has not RXed so we can't assume the AP believe us awake
1778                  */
1779         } else {
1780                 /* 21112005 - tx again null without PS bit if lost */
1781                 if ((ieee->sta_sleep == 0) && !success) {
1782                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1783                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1784                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1785                 }
1786         }
1787         spin_unlock_irqrestore(&ieee->lock, flags);
1788 }
1789 EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1790 
1791 static void ieee80211_process_action(struct ieee80211_device *ieee,
1792                                      struct sk_buff *skb)
1793 {
1794         struct rtl_80211_hdr *header = (struct rtl_80211_hdr *)skb->data;
1795         u8 *act = ieee80211_get_payload(header);
1796         u8 tmp = 0;
1797 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1798         if (!act) {
1799                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1800                 return;
1801         }
1802         tmp = *act;
1803         act++;
1804         switch (tmp) {
1805         case ACT_CAT_BA:
1806                 if (*act == ACT_ADDBAREQ)
1807                         ieee80211_rx_ADDBAReq(ieee, skb);
1808                 else if (*act == ACT_ADDBARSP)
1809                         ieee80211_rx_ADDBARsp(ieee, skb);
1810                 else if (*act == ACT_DELBA)
1811                         ieee80211_rx_DELBA(ieee, skb);
1812                 break;
1813         default:
1814                 break;
1815         }
1816         return;
1817 }
1818 
1819 static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1820                                           struct sk_buff *skb)
1821 {
1822         /* default support N mode, disable halfNmode */
1823         bool bSupportNmode = true, bHalfSupportNmode = false;
1824         u16 errcode;
1825         u8 *challenge;
1826         int chlen = 0;
1827         u32 iotAction;
1828 
1829         errcode = auth_parse(skb, &challenge, &chlen);
1830         if (!errcode) {
1831                 if (ieee->open_wep || !challenge) {
1832                         ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1833                         ieee->softmac_stats.rx_auth_rs_ok++;
1834                         iotAction = ieee->pHTInfo->IOTAction;
1835                         if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1836                                 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1837                                         /* WEP or TKIP encryption */
1838                                         if (IsHTHalfNmodeAPs(ieee)) {
1839                                                 bSupportNmode = true;
1840                                                 bHalfSupportNmode = true;
1841                                         } else {
1842                                                 bSupportNmode = false;
1843                                                 bHalfSupportNmode = false;
1844                                         }
1845                                         netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1846                                                         bSupportNmode,
1847                                                         bHalfSupportNmode);
1848                                 }
1849                         }
1850                         /* Dummy wirless mode setting- avoid encryption issue */
1851                         if (bSupportNmode) {
1852                                 /* N mode setting */
1853                                 ieee->SetWirelessMode(ieee->dev,
1854                                                 ieee->current_network.mode);
1855                         } else {
1856                                 /* b/g mode setting - TODO */
1857                                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1858                         }
1859 
1860                         if (ieee->current_network.mode == IEEE_N_24G &&
1861                                         bHalfSupportNmode) {
1862                                 netdev_dbg(ieee->dev, "enter half N mode\n");
1863                                 ieee->bHalfWirelessN24GMode = true;
1864                         } else {
1865                                 ieee->bHalfWirelessN24GMode = false;
1866                         }
1867                         ieee80211_associate_step2(ieee);
1868                 } else {
1869                         ieee80211_auth_challenge(ieee, challenge, chlen);
1870                 }
1871         } else {
1872                 ieee->softmac_stats.rx_auth_rs_err++;
1873                 IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1874                 ieee80211_associate_abort(ieee);
1875         }
1876 }
1877 
1878 inline int
1879 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1880                            struct ieee80211_rx_stats *rx_stats, u16 type,
1881                            u16 stype)
1882 {
1883         struct rtl_80211_hdr_3addr *header = (struct rtl_80211_hdr_3addr *)skb->data;
1884         u16 errcode;
1885         int aid;
1886         struct ieee80211_assoc_response_frame *assoc_resp;
1887 //      struct ieee80211_info_element *info_element;
1888 
1889         if (!ieee->proto_started)
1890                 return 0;
1891 
1892         if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1893                                 ieee->iw_mode == IW_MODE_INFRA &&
1894                                 ieee->state == IEEE80211_LINKED))
1895                 tasklet_schedule(&ieee->ps_task);
1896 
1897         if (WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
1898             WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
1899                 ieee->last_rx_ps_time = jiffies;
1900 
1901         switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1902         case IEEE80211_STYPE_ASSOC_RESP:
1903         case IEEE80211_STYPE_REASSOC_RESP:
1904                 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1905                                 WLAN_FC_GET_STYPE(header->frame_ctl));
1906                 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1907                     ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1908                     ieee->iw_mode == IW_MODE_INFRA) {
1909                         struct ieee80211_network network_resp;
1910                         struct ieee80211_network *network = &network_resp;
1911 
1912                         errcode = assoc_parse(ieee, skb, &aid);
1913                         if (!errcode) {
1914                                 ieee->state = IEEE80211_LINKED;
1915                                 ieee->assoc_id = aid;
1916                                 ieee->softmac_stats.rx_ass_ok++;
1917                                 /* station support qos */
1918                                 /* Let the register setting defaultly with Legacy station */
1919                                 if (ieee->qos_support) {
1920                                         assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
1921                                         memset(network, 0, sizeof(*network));
1922                                         if (ieee80211_parse_info_param(ieee, assoc_resp->info_element,\
1923                                                                        rx_stats->len - sizeof(*assoc_resp), \
1924                                                                        network, rx_stats)) {
1925                                                 return 1;
1926                                         } else {
1927                                                 //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
1928                                                 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1929                                                 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1930                                         }
1931                                         if (ieee->handle_assoc_response)
1932                                                 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
1933                                 }
1934                                 ieee80211_associate_complete(ieee);
1935                         } else {
1936                                 /* aid could not been allocated */
1937                                 ieee->softmac_stats.rx_ass_err++;
1938                                 printk("Association response status code 0x%x\n",
1939                                        errcode);
1940                                 IEEE80211_DEBUG_MGMT("Association response status code 0x%x\n",
1941                                                      errcode);
1942                                 if (ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT)
1943                                         schedule_work(&ieee->associate_procedure_wq);
1944                                 else
1945                                         ieee80211_associate_abort(ieee);
1946                         }
1947                 }
1948                 break;
1949 
1950         case IEEE80211_STYPE_ASSOC_REQ:
1951         case IEEE80211_STYPE_REASSOC_REQ:
1952                 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1953                     ieee->iw_mode == IW_MODE_MASTER)
1954                         ieee80211_rx_assoc_rq(ieee, skb);
1955                 break;
1956 
1957         case IEEE80211_STYPE_AUTH:
1958                 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
1959                         if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
1960                             && ieee->iw_mode == IW_MODE_INFRA) {
1961                                 IEEE80211_DEBUG_MGMT("Received auth response");
1962                                 ieee80211_check_auth_response(ieee, skb);
1963                         } else if (ieee->iw_mode == IW_MODE_MASTER) {
1964                                 ieee80211_rx_auth_rq(ieee, skb);
1965                         }
1966                 }
1967                 break;
1968 
1969         case IEEE80211_STYPE_PROBE_REQ:
1970                 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
1971                     ((ieee->iw_mode == IW_MODE_ADHOC ||
1972                       ieee->iw_mode == IW_MODE_MASTER) &&
1973                      ieee->state == IEEE80211_LINKED)) {
1974                         ieee80211_rx_probe_rq(ieee, skb);
1975                 }
1976                 break;
1977 
1978         case IEEE80211_STYPE_DISASSOC:
1979         case IEEE80211_STYPE_DEAUTH:
1980                 /* FIXME for now repeat all the association procedure
1981                 * both for disassociation and deauthentication
1982                 */
1983                 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1984                     ieee->state == IEEE80211_LINKED &&
1985                     ieee->iw_mode == IW_MODE_INFRA) {
1986                         ieee->state = IEEE80211_ASSOCIATING;
1987                         ieee->softmac_stats.reassoc++;
1988 
1989                         notify_wx_assoc_event(ieee);
1990                         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1991                         RemovePeerTS(ieee, header->addr2);
1992                         schedule_work(&ieee->associate_procedure_wq);
1993                 }
1994                 break;
1995         case IEEE80211_STYPE_MANAGE_ACT:
1996                 ieee80211_process_action(ieee, skb);
1997                 break;
1998         default:
1999                 return -1;
2000         }
2001 
2002         //dev_kfree_skb_any(skb);
2003         return 0;
2004 }
2005 
2006 /* The following are for a simpler TX queue management.
2007  * Instead of using netif_[stop/wake]_queue, the driver
2008  * will use these two functions (plus a reset one) that
2009  * will internally call the kernel netif_* and take care
2010  * of the ieee802.11 fragmentation.
2011  * So, the driver receives a fragment at a time and might
2012  * call the stop function when it wants, without taking
2013  * care to have enough room to TX an entire packet.
2014  * This might be useful if each fragment needs its own
2015  * descriptor. Thus, just keeping a total free memory > than
2016  * the max fragmentation threshold is not enough. If the
2017  * ieee802.11 stack passed a TXB struct, then you would need
2018  * to keep N free descriptors where
2019  * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
2020  * In this way you need just one and the 802.11 stack
2021  * will take care of buffering fragments and pass them to
2022  * to the driver later, when it wakes the queue.
2023  */
2024 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2025 {
2026         unsigned int queue_index = txb->queue_index;
2027         unsigned long flags;
2028         int  i;
2029         struct cb_desc *tcb_desc = NULL;
2030 
2031         spin_lock_irqsave(&ieee->lock, flags);
2032 
2033         /* called with 2nd parm 0, no tx mgmt lock required */
2034         ieee80211_sta_wakeup(ieee, 0);
2035 
2036         /* update the tx status */
2037         ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
2038         ieee->stats.tx_packets++;
2039         tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2040         if (tcb_desc->bMulticast)
2041                 ieee->stats.multicast++;
2042 
2043         /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2044         for (i = 0; i < txb->nr_frags; i++) {
2045 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2046                 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2047 #else
2048                 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2049 #endif
2050                     (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) || \
2051                     (ieee->queue_stop)) {
2052                         /* insert the skb packet to the wait queue */
2053                         /* as for the completion function, it does not need
2054                          * to check it any more.
2055                          * */
2056                         //printk("error:no descriptor left@queue_index %d\n", queue_index);
2057                         //ieee80211_stop_queue(ieee);
2058 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2059                         skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2060 #else
2061                         skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2062 #endif
2063                 } else {
2064                         ieee->softmac_data_hard_start_xmit(txb->fragments[i],
2065                                                            ieee->dev, ieee->rate);
2066                         //ieee->stats.tx_packets++;
2067                         //ieee->stats.tx_bytes += txb->fragments[i]->len;
2068                         //ieee->dev->trans_start = jiffies;
2069                 }
2070         }
2071         ieee80211_txb_free(txb);
2072 
2073 //exit:
2074         spin_unlock_irqrestore(&ieee->lock, flags);
2075 }
2076 EXPORT_SYMBOL(ieee80211_softmac_xmit);
2077 
2078 /* called with ieee->lock acquired */
2079 static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2080 {
2081         int i;
2082         for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2083                 if (ieee->queue_stop) {
2084                         ieee->tx_pending.frag = i;
2085                         return;
2086                 } else {
2087                         ieee->softmac_data_hard_start_xmit(ieee->tx_pending.txb->fragments[i],
2088                                                            ieee->dev, ieee->rate);
2089                         //(i+1)<ieee->tx_pending.txb->nr_frags);
2090                         ieee->stats.tx_packets++;
2091                         netif_trans_update(ieee->dev);
2092                 }
2093         }
2094 
2095         ieee80211_txb_free(ieee->tx_pending.txb);
2096         ieee->tx_pending.txb = NULL;
2097 }
2098 
2099 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2100 {
2101         unsigned long flags;
2102 
2103         spin_lock_irqsave(&ieee->lock, flags);
2104         init_mgmt_queue(ieee);
2105         if (ieee->tx_pending.txb) {
2106                 ieee80211_txb_free(ieee->tx_pending.txb);
2107                 ieee->tx_pending.txb = NULL;
2108         }
2109         ieee->queue_stop = 0;
2110         spin_unlock_irqrestore(&ieee->lock, flags);
2111 }
2112 EXPORT_SYMBOL(ieee80211_reset_queue);
2113 
2114 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2115 {
2116         unsigned long flags;
2117         struct sk_buff *skb;
2118         struct rtl_80211_hdr_3addr  *header;
2119 
2120         spin_lock_irqsave(&ieee->lock, flags);
2121         if (!ieee->queue_stop)
2122                 goto exit;
2123 
2124         ieee->queue_stop = 0;
2125 
2126         if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
2127                 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
2128                         header = (struct rtl_80211_hdr_3addr  *)skb->data;
2129 
2130                         header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2131 
2132                         if (ieee->seq_ctrl[0] == 0xFFF)
2133                                 ieee->seq_ctrl[0] = 0;
2134                         else
2135                                 ieee->seq_ctrl[0]++;
2136 
2137                         ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
2138                         //dev_kfree_skb_any(skb);//edit by thomas
2139                 }
2140         }
2141         if (!ieee->queue_stop && ieee->tx_pending.txb)
2142                 ieee80211_resume_tx(ieee);
2143 
2144         if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
2145                 ieee->softmac_stats.swtxawake++;
2146                 netif_wake_queue(ieee->dev);
2147         }
2148 exit:
2149         spin_unlock_irqrestore(&ieee->lock, flags);
2150 }
2151 EXPORT_SYMBOL(ieee80211_wake_queue);
2152 
2153 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2154 {
2155         //unsigned long flags;
2156         //spin_lock_irqsave(&ieee->lock,flags);
2157 
2158         if (!netif_queue_stopped(ieee->dev)) {
2159                 netif_stop_queue(ieee->dev);
2160                 ieee->softmac_stats.swtxstop++;
2161         }
2162         ieee->queue_stop = 1;
2163         //spin_unlock_irqrestore(&ieee->lock,flags);
2164 }
2165 EXPORT_SYMBOL(ieee80211_stop_queue);
2166 
2167 /* called in user context only */
2168 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2169 {
2170         ieee->assoc_id = 1;
2171 
2172         if (ieee->current_network.ssid_len == 0) {
2173                 strncpy(ieee->current_network.ssid,
2174                         IEEE80211_DEFAULT_TX_ESSID,
2175                         IW_ESSID_MAX_SIZE);
2176 
2177                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2178                 ieee->ssid_set = 1;
2179         }
2180 
2181         memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2182 
2183         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2184         ieee->state = IEEE80211_LINKED;
2185         ieee->link_change(ieee->dev);
2186         notify_wx_assoc_event(ieee);
2187 
2188         if (ieee->data_hard_resume)
2189                 ieee->data_hard_resume(ieee->dev);
2190 
2191         netif_carrier_on(ieee->dev);
2192 }
2193 
2194 static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2195 {
2196         if (ieee->raw_tx) {
2197                 if (ieee->data_hard_resume)
2198                         ieee->data_hard_resume(ieee->dev);
2199 
2200                 netif_carrier_on(ieee->dev);
2201         }
2202 }
2203 static void ieee80211_start_ibss_wq(struct work_struct *work)
2204 {
2205         struct delayed_work *dwork = to_delayed_work(work);
2206         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2207         /* iwconfig mode ad-hoc will schedule this and return
2208          * on the other hand this will block further iwconfig SET
2209          * operations because of the wx_mutex hold.
2210          * Anyway some most set operations set a flag to speed-up
2211          * (abort) this wq (when syncro scanning) before sleeping
2212          * on the semaphore
2213          */
2214         if (!ieee->proto_started) {
2215                 printk("==========oh driver down return\n");
2216                 return;
2217         }
2218         mutex_lock(&ieee->wx_mutex);
2219 
2220         if (ieee->current_network.ssid_len == 0) {
2221                 strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
2222                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2223                 ieee->ssid_set = 1;
2224         }
2225 
2226         /* check if we have this cell in our network list */
2227         ieee80211_softmac_check_all_nets(ieee);
2228 
2229 //      if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2230         if (ieee->state == IEEE80211_NOLINK)
2231                 ieee->current_network.channel = 6;
2232         /* if not then the state is not linked. Maybe the user switched to
2233          * ad-hoc mode just after being in monitor mode, or just after
2234          * being very few time in managed mode (so the card have had no
2235          * time to scan all the chans..) or we have just run up the iface
2236          * after setting ad-hoc mode. So we have to give another try..
2237          * Here, in ibss mode, should be safe to do this without extra care
2238          * (in bss mode we had to make sure no-one tryed to associate when
2239          * we had just checked the ieee->state and we was going to start the
2240          * scan) beacause in ibss mode the ieee80211_new_net function, when
2241          * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2242          * so, at worst, we waste a bit of time to initiate an unneeded syncro
2243          * scan, that will stop at the first round because it sees the state
2244          * associated.
2245          */
2246         if (ieee->state == IEEE80211_NOLINK)
2247                 ieee80211_start_scan_syncro(ieee);
2248 
2249         /* the network definitively is not here.. create a new cell */
2250         if (ieee->state == IEEE80211_NOLINK) {
2251                 printk("creating new IBSS cell\n");
2252                 if (!ieee->wap_set)
2253                         eth_random_addr(ieee->current_network.bssid);
2254 
2255                 if (ieee->modulation & IEEE80211_CCK_MODULATION) {
2256                         ieee->current_network.rates_len = 4;
2257 
2258                         ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2259                         ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2260                         ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2261                         ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2262                 } else {
2263                         ieee->current_network.rates_len = 0;
2264                 }
2265                 if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
2266                         ieee->current_network.rates_ex_len = 8;
2267 
2268                         ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2269                         ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2270                         ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2271                         ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2272                         ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2273                         ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2274                         ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2275                         ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2276 
2277                         ieee->rate = 108;
2278                 } else {
2279                         ieee->current_network.rates_ex_len = 0;
2280                         ieee->rate = 22;
2281                 }
2282 
2283                 // By default, WMM function will be disabled in IBSS mode
2284                 ieee->current_network.QoS_Enable = 0;
2285                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2286                 ieee->current_network.atim_window = 0;
2287                 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2288                 if (ieee->short_slot)
2289                         ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2290         }
2291 
2292         ieee->state = IEEE80211_LINKED;
2293 
2294         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2295         ieee->link_change(ieee->dev);
2296 
2297         notify_wx_assoc_event(ieee);
2298 
2299         ieee80211_start_send_beacons(ieee);
2300 
2301         if (ieee->data_hard_resume)
2302                 ieee->data_hard_resume(ieee->dev);
2303         netif_carrier_on(ieee->dev);
2304 
2305         mutex_unlock(&ieee->wx_mutex);
2306 }
2307 
2308 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2309 {
2310         schedule_delayed_work(&ieee->start_ibss_wq, 150);
2311 }
2312 
2313 /* this is called only in user context, with wx_mutex held */
2314 void ieee80211_start_bss(struct ieee80211_device *ieee)
2315 {
2316         unsigned long flags;
2317         //
2318         // Ref: 802.11d 11.1.3.3
2319         // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2320         //
2321         if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
2322                 if (!ieee->bGlobalDomain)
2323                         return;
2324         }
2325         /* check if we have already found the net we
2326          * are interested in (if any).
2327          * if not (we are disassociated and we are not
2328          * in associating / authenticating phase) start the background scanning.
2329          */
2330         ieee80211_softmac_check_all_nets(ieee);
2331 
2332         /* ensure no-one start an associating process (thus setting
2333          * the ieee->state to ieee80211_ASSOCIATING) while we
2334          * have just cheked it and we are going to enable scan.
2335          * The ieee80211_new_net function is always called with
2336          * lock held (from both ieee80211_softmac_check_all_nets and
2337          * the rx path), so we cannot be in the middle of such function
2338          */
2339         spin_lock_irqsave(&ieee->lock, flags);
2340 
2341         if (ieee->state == IEEE80211_NOLINK) {
2342                 ieee->actscanning = true;
2343                 ieee80211_start_scan(ieee);
2344         }
2345         spin_unlock_irqrestore(&ieee->lock, flags);
2346 }
2347 
2348 /* called only in userspace context */
2349 void ieee80211_disassociate(struct ieee80211_device *ieee)
2350 {
2351         netif_carrier_off(ieee->dev);
2352         if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2353                 ieee80211_reset_queue(ieee);
2354 
2355         if (ieee->data_hard_stop)
2356                 ieee->data_hard_stop(ieee->dev);
2357         if (IS_DOT11D_ENABLE(ieee))
2358                 dot11d_reset(ieee);
2359         ieee->state = IEEE80211_NOLINK;
2360         ieee->is_set_key = false;
2361         ieee->link_change(ieee->dev);
2362         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2363         notify_wx_assoc_event(ieee);
2364 }
2365 EXPORT_SYMBOL(ieee80211_disassociate);
2366 
2367 static void ieee80211_associate_retry_wq(struct work_struct *work)
2368 {
2369         struct delayed_work *dwork = to_delayed_work(work);
2370         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2371         unsigned long flags;
2372 
2373         mutex_lock(&ieee->wx_mutex);
2374         if (!ieee->proto_started)
2375                 goto exit;
2376 
2377         if (ieee->state != IEEE80211_ASSOCIATING_RETRY)
2378                 goto exit;
2379 
2380         /* until we do not set the state to IEEE80211_NOLINK
2381         * there are no possibility to have someone else trying
2382         * to start an association procedure (we get here with
2383         * ieee->state = IEEE80211_ASSOCIATING).
2384         * When we set the state to IEEE80211_NOLINK it is possible
2385         * that the RX path run an attempt to associate, but
2386         * both ieee80211_softmac_check_all_nets and the
2387         * RX path works with ieee->lock held so there are no
2388         * problems. If we are still disassociated then start a scan.
2389         * the lock here is necessary to ensure no one try to start
2390         * an association procedure when we have just checked the
2391         * state and we are going to start the scan.
2392         */
2393         ieee->state = IEEE80211_NOLINK;
2394 
2395         ieee80211_softmac_check_all_nets(ieee);
2396 
2397         spin_lock_irqsave(&ieee->lock, flags);
2398 
2399         if (ieee->state == IEEE80211_NOLINK)
2400                 ieee80211_start_scan(ieee);
2401 
2402         spin_unlock_irqrestore(&ieee->lock, flags);
2403 
2404 exit:
2405         mutex_unlock(&ieee->wx_mutex);
2406 }
2407 
2408 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2409 {
2410         u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2411 
2412         struct sk_buff *skb;
2413         struct ieee80211_probe_response *b;
2414 
2415         skb = ieee80211_probe_resp(ieee, broadcast_addr);
2416 
2417         if (!skb)
2418                 return NULL;
2419 
2420         b = (struct ieee80211_probe_response *)skb->data;
2421         b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2422 
2423         return skb;
2424 }
2425 
2426 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2427 {
2428         struct sk_buff *skb;
2429         struct ieee80211_probe_response *b;
2430 
2431         skb = ieee80211_get_beacon_(ieee);
2432         if (!skb)
2433                 return NULL;
2434 
2435         b = (struct ieee80211_probe_response *)skb->data;
2436         b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2437 
2438         if (ieee->seq_ctrl[0] == 0xFFF)
2439                 ieee->seq_ctrl[0] = 0;
2440         else
2441                 ieee->seq_ctrl[0]++;
2442 
2443         return skb;
2444 }
2445 EXPORT_SYMBOL(ieee80211_get_beacon);
2446 
2447 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2448 {
2449         ieee->sync_scan_hurryup = 1;
2450         mutex_lock(&ieee->wx_mutex);
2451         ieee80211_stop_protocol(ieee);
2452         mutex_unlock(&ieee->wx_mutex);
2453 }
2454 EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2455 
2456 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2457 {
2458         if (!ieee->proto_started)
2459                 return;
2460 
2461         ieee->proto_started = 0;
2462 
2463         ieee80211_stop_send_beacons(ieee);
2464         del_timer_sync(&ieee->associate_timer);
2465         cancel_delayed_work(&ieee->associate_retry_wq);
2466         cancel_delayed_work(&ieee->start_ibss_wq);
2467         ieee80211_stop_scan(ieee);
2468 
2469         ieee80211_disassociate(ieee);
2470         RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2471 }
2472 
2473 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2474 {
2475         ieee->sync_scan_hurryup = 0;
2476         mutex_lock(&ieee->wx_mutex);
2477         ieee80211_start_protocol(ieee);
2478         mutex_unlock(&ieee->wx_mutex);
2479 }
2480 EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2481 
2482 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2483 {
2484         short ch = 0;
2485         int i = 0;
2486 
2487         if (ieee->proto_started)
2488                 return;
2489 
2490         ieee->proto_started = 1;
2491 
2492         if (ieee->current_network.channel == 0) {
2493                 do {
2494                         ch++;
2495                         if (ch > MAX_CHANNEL_NUMBER)
2496                                 return; /* no channel found */
2497                 } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2498                 ieee->current_network.channel = ch;
2499         }
2500 
2501         if (ieee->current_network.beacon_interval == 0)
2502                 ieee->current_network.beacon_interval = 100;
2503 //      printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
2504 //      ieee->set_chan(ieee->dev,ieee->current_network.channel);
2505 
2506         for (i = 0; i < 17; i++) {
2507                 ieee->last_rxseq_num[i] = -1;
2508                 ieee->last_rxfrag_num[i] = -1;
2509                 ieee->last_packet_time[i] = 0;
2510         }
2511 
2512         ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2513 
2514         /* if the user set the MAC of the ad-hoc cell and then
2515          * switch to managed mode, shall we  make sure that association
2516          * attempts does not fail just because the user provide the essid
2517          * and the nic is still checking for the AP MAC ??
2518          */
2519         if (ieee->iw_mode == IW_MODE_INFRA)
2520                 ieee80211_start_bss(ieee);
2521 
2522         else if (ieee->iw_mode == IW_MODE_ADHOC)
2523                 ieee80211_start_ibss(ieee);
2524 
2525         else if (ieee->iw_mode == IW_MODE_MASTER)
2526                 ieee80211_start_master_bss(ieee);
2527 
2528         else if (ieee->iw_mode == IW_MODE_MONITOR)
2529                 ieee80211_start_monitor_mode(ieee);
2530 }
2531 
2532 #define DRV_NAME  "Ieee80211"
2533 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2534 {
2535         int i;
2536         memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2537 
2538         ieee->state = IEEE80211_NOLINK;
2539         ieee->sync_scan_hurryup = 0;
2540         for (i = 0; i < 5; i++)
2541                 ieee->seq_ctrl[i] = 0;
2542 
2543         ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_KERNEL);
2544         if (!ieee->dot11d_info)
2545                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2546         //added for  AP roaming
2547         ieee->LinkDetectInfo.SlotNum = 2;
2548         ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
2549         ieee->LinkDetectInfo.NumRecvDataInPeriod = 0;
2550 
2551         ieee->assoc_id = 0;
2552         ieee->queue_stop = 0;
2553         ieee->scanning = 0;
2554         ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2555         ieee->wap_set = 0;
2556         ieee->ssid_set = 0;
2557         ieee->proto_started = 0;
2558         ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2559         ieee->rate = 22;
2560         ieee->ps = IEEE80211_PS_DISABLED;
2561         ieee->sta_sleep = 0;
2562         ieee->Regdot11HTOperationalRateSet[0] = 0xff;//support MCS 0~7
2563         ieee->Regdot11HTOperationalRateSet[1] = 0xff;//support MCS 8~15
2564         ieee->Regdot11HTOperationalRateSet[4] = 0x01;
2565         //added by amy
2566         ieee->actscanning = false;
2567         ieee->beinretry = false;
2568         ieee->is_set_key = false;
2569         init_mgmt_queue(ieee);
2570 
2571         ieee->sta_edca_param[0] = 0x0000A403;
2572         ieee->sta_edca_param[1] = 0x0000A427;
2573         ieee->sta_edca_param[2] = 0x005E4342;
2574         ieee->sta_edca_param[3] = 0x002F3262;
2575         ieee->aggregation = true;
2576         ieee->enable_rx_imm_BA = true;
2577         ieee->tx_pending.txb = NULL;
2578 
2579         timer_setup(&ieee->associate_timer, ieee80211_associate_abort_cb, 0);
2580 
2581         timer_setup(&ieee->beacon_timer, ieee80211_send_beacon_cb, 0);
2582 
2583         INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2584         INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2585         INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2586         INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2587         INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2588         INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2589 
2590         mutex_init(&ieee->wx_mutex);
2591         mutex_init(&ieee->scan_mutex);
2592 
2593         spin_lock_init(&ieee->mgmt_tx_lock);
2594         spin_lock_init(&ieee->beacon_lock);
2595 
2596         tasklet_init(&ieee->ps_task,
2597                      (void(*)(unsigned long)) ieee80211_sta_ps,
2598                      (unsigned long)ieee);
2599 }
2600 
2601 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2602 {
2603         mutex_lock(&ieee->wx_mutex);
2604         kfree(ieee->dot11d_info);
2605         ieee->dot11d_info = NULL;
2606         del_timer_sync(&ieee->associate_timer);
2607 
2608         cancel_delayed_work(&ieee->associate_retry_wq);
2609 
2610         mutex_unlock(&ieee->wx_mutex);
2611 }
2612 
2613 /********************************************************
2614  * Start of WPA code.                                   *
2615  * this is stolen from the ipw2200 driver               *
2616  ********************************************************/
2617 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2618 {
2619         /* This is called when wpa_supplicant loads and closes the driver
2620          * interface. */
2621         printk("%s WPA\n", value ? "enabling" : "disabling");
2622         ieee->wpa_enabled = value;
2623         return 0;
2624 }
2625 
2626 static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2627                                       char *wpa_ie, int wpa_ie_len)
2628 {
2629         /* make sure WPA is enabled */
2630         ieee80211_wpa_enable(ieee, 1);
2631 
2632         ieee80211_disassociate(ieee);
2633 }
2634 
2635 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2636 {
2637         int ret = 0;
2638 
2639         switch (command) {
2640         case IEEE_MLME_STA_DEAUTH:
2641                 // silently ignore
2642                 break;
2643 
2644         case IEEE_MLME_STA_DISASSOC:
2645                 ieee80211_disassociate(ieee);
2646                 break;
2647 
2648         default:
2649                 printk("Unknown MLME request: %d\n", command);
2650                 ret = -EOPNOTSUPP;
2651         }
2652 
2653         return ret;
2654 }
2655 
2656 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2657                               struct ieee_param *param, int plen)
2658 {
2659         u8 *buf;
2660 
2661         if (param->u.wpa_ie.len > MAX_WPA_IE_LEN)
2662                 return -EINVAL;
2663 
2664         if (param->u.wpa_ie.len) {
2665                 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2666                               GFP_KERNEL);
2667                 if (!buf)
2668                         return -ENOMEM;
2669 
2670                 kfree(ieee->wpa_ie);
2671                 ieee->wpa_ie = buf;
2672                 ieee->wpa_ie_len = param->u.wpa_ie.len;
2673         } else {
2674                 kfree(ieee->wpa_ie);
2675                 ieee->wpa_ie = NULL;
2676                 ieee->wpa_ie_len = 0;
2677         }
2678 
2679         ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2680         return 0;
2681 }
2682 
2683 #define AUTH_ALG_OPEN_SYSTEM                    0x1
2684 #define AUTH_ALG_SHARED_KEY                     0x2
2685 
2686 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2687 {
2688         struct ieee80211_security sec = {
2689                 .flags = SEC_AUTH_MODE,
2690         };
2691 
2692         if (value & AUTH_ALG_SHARED_KEY) {
2693                 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2694                 ieee->open_wep = 0;
2695                 ieee->auth_mode = 1;
2696         } else if (value & AUTH_ALG_OPEN_SYSTEM) {
2697                 sec.auth_mode = WLAN_AUTH_OPEN;
2698                 ieee->open_wep = 1;
2699                 ieee->auth_mode = 0;
2700         } else if (value & IW_AUTH_ALG_LEAP) {
2701                 sec.auth_mode = WLAN_AUTH_LEAP;
2702                 ieee->open_wep = 1;
2703                 ieee->auth_mode = 2;
2704         }
2705 
2706         if (ieee->set_security)
2707                 ieee->set_security(ieee->dev, &sec);
2708         //else
2709         //      ret = -EOPNOTSUPP;
2710 
2711         return 0;
2712 }
2713 
2714 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2715 {
2716         int ret = 0;
2717         unsigned long flags;
2718 
2719         switch (name) {
2720         case IEEE_PARAM_WPA_ENABLED:
2721                 ret = ieee80211_wpa_enable(ieee, value);
2722                 break;
2723 
2724         case IEEE_PARAM_TKIP_COUNTERMEASURES:
2725                 ieee->tkip_countermeasures = value;
2726                 break;
2727 
2728         case IEEE_PARAM_DROP_UNENCRYPTED: {
2729                 /* HACK:
2730                  *
2731                  * wpa_supplicant calls set_wpa_enabled when the driver
2732                  * is loaded and unloaded, regardless of if WPA is being
2733                  * used.  No other calls are made which can be used to
2734                  * determine if encryption will be used or not prior to
2735                  * association being expected.  If encryption is not being
2736                  * used, drop_unencrypted is set to false, else true -- we
2737                  * can use this to determine if the CAP_PRIVACY_ON bit should
2738                  * be set.
2739                  */
2740                 struct ieee80211_security sec = {
2741                         .flags = SEC_ENABLED,
2742                         .enabled = value,
2743                 };
2744                 ieee->drop_unencrypted = value;
2745                 /* We only change SEC_LEVEL for open mode. Others
2746                  * are set by ipw_wpa_set_encryption.
2747                  */
2748                 if (!value) {
2749                         sec.flags |= SEC_LEVEL;
2750                         sec.level = SEC_LEVEL_0;
2751                 } else {
2752                         sec.flags |= SEC_LEVEL;
2753                         sec.level = SEC_LEVEL_1;
2754                 }
2755                 if (ieee->set_security)
2756                         ieee->set_security(ieee->dev, &sec);
2757                 break;
2758         }
2759 
2760         case IEEE_PARAM_PRIVACY_INVOKED:
2761                 ieee->privacy_invoked = value;
2762                 break;
2763 
2764         case IEEE_PARAM_AUTH_ALGS:
2765                 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2766                 break;
2767 
2768         case IEEE_PARAM_IEEE_802_1X:
2769                 ieee->ieee802_1x = value;
2770                 break;
2771         case IEEE_PARAM_WPAX_SELECT:
2772                 // added for WPA2 mixed mode
2773                 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2774                 ieee->wpax_type_set = 1;
2775                 ieee->wpax_type_notify = value;
2776                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2777                 break;
2778 
2779         default:
2780                 printk("Unknown WPA param: %d\n", name);
2781                 ret = -EOPNOTSUPP;
2782         }
2783 
2784         return ret;
2785 }
2786 
2787 /* implementation borrowed from hostap driver */
2788 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2789                                   struct ieee_param *param, int param_len)
2790 {
2791         int ret = 0;
2792         const char *module = NULL;
2793 
2794         struct ieee80211_crypto_ops *ops = NULL;
2795         struct ieee80211_crypt_data **crypt;
2796 
2797         struct ieee80211_security sec = {
2798                 .flags = 0,
2799         };
2800 
2801         param->u.crypt.err = 0;
2802         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2803 
2804         if (param_len !=
2805             (int)((char *)param->u.crypt.key - (char *)param) +
2806             param->u.crypt.key_len) {
2807                 printk("Len mismatch %d, %d\n", param_len,
2808                                param->u.crypt.key_len);
2809                 return -EINVAL;
2810         }
2811         if (is_broadcast_ether_addr(param->sta_addr)) {
2812                 if (param->u.crypt.idx >= WEP_KEYS)
2813                         return -EINVAL;
2814                 crypt = &ieee->crypt[param->u.crypt.idx];
2815         } else {
2816                 return -EINVAL;
2817         }
2818 
2819         if (strcmp(param->u.crypt.alg, "none") == 0) {
2820                 if (crypt) {
2821                         sec.enabled = 0;
2822                         // FIXME FIXME
2823                         //sec.encrypt = 0;
2824                         sec.level = SEC_LEVEL_0;
2825                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
2826                         ieee80211_crypt_delayed_deinit(ieee, crypt);
2827                 }
2828                 goto done;
2829         }
2830         sec.enabled = 1;
2831 // FIXME FIXME
2832 //      sec.encrypt = 1;
2833         sec.flags |= SEC_ENABLED;
2834 
2835         /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2836         if (!(ieee->host_encrypt || ieee->host_decrypt) &&
2837             strcmp(param->u.crypt.alg, "TKIP"))
2838                 goto skip_host_crypt;
2839 
2840         //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
2841         if (!strcmp(param->u.crypt.alg, "WEP"))
2842                 module = "ieee80211_crypt_wep";
2843         else if (!strcmp(param->u.crypt.alg, "TKIP"))
2844                 module = "ieee80211_crypt_tkip";
2845         else if (!strcmp(param->u.crypt.alg, "CCMP"))
2846                 module = "ieee80211_crypt_ccmp";
2847         if (module)
2848                 ops = try_then_request_module(ieee80211_get_crypto_ops(param->u.crypt.alg),
2849                                               module);
2850         if (!ops) {
2851                 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
2852                 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
2853                 ret = -EINVAL;
2854                 goto done;
2855         }
2856 
2857         if (!*crypt || (*crypt)->ops != ops) {
2858                 struct ieee80211_crypt_data *new_crypt;
2859 
2860                 ieee80211_crypt_delayed_deinit(ieee, crypt);
2861 
2862                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
2863                 if (!new_crypt) {
2864                         ret = -ENOMEM;
2865                         goto done;
2866                 }
2867                 new_crypt->ops = ops;
2868                 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
2869                         new_crypt->priv =
2870                                 new_crypt->ops->init(param->u.crypt.idx);
2871 
2872                 if (!new_crypt->priv) {
2873                         kfree(new_crypt);
2874                         param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
2875                         ret = -EINVAL;
2876                         goto done;
2877                 }
2878 
2879                 *crypt = new_crypt;
2880         }
2881 
2882         if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
2883             (*crypt)->ops->set_key(param->u.crypt.key,
2884                                    param->u.crypt.key_len, param->u.crypt.seq,
2885                                    (*crypt)->priv) < 0) {
2886                 printk("key setting failed\n");
2887                 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
2888                 ret = -EINVAL;
2889                 goto done;
2890         }
2891 
2892  skip_host_crypt:
2893         if (param->u.crypt.set_tx) {
2894                 ieee->tx_keyidx = param->u.crypt.idx;
2895                 sec.active_key = param->u.crypt.idx;
2896                 sec.flags |= SEC_ACTIVE_KEY;
2897         } else {
2898                 sec.flags &= ~SEC_ACTIVE_KEY;
2899         }
2900         memcpy(sec.keys[param->u.crypt.idx],
2901                param->u.crypt.key,
2902                param->u.crypt.key_len);
2903         sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
2904         sec.flags |= (1 << param->u.crypt.idx);
2905 
2906         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2907                 sec.flags |= SEC_LEVEL;
2908                 sec.level = SEC_LEVEL_1;
2909         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2910                 sec.flags |= SEC_LEVEL;
2911                 sec.level = SEC_LEVEL_2;
2912         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2913                 sec.flags |= SEC_LEVEL;
2914                 sec.level = SEC_LEVEL_3;
2915         }
2916  done:
2917         if (ieee->set_security)
2918                 ieee->set_security(ieee->dev, &sec);
2919 
2920         /* Do not reset port if card is in Managed mode since resetting will
2921          * generate new IEEE 802.11 authentication which may end up in looping
2922          * with IEEE 802.1X.  If your hardware requires a reset after WEP
2923          * configuration (for example... Prism2), implement the reset_port in
2924          * the callbacks structures used to initialize the 802.11 stack. */
2925         if (ieee->reset_on_keychange &&
2926             ieee->iw_mode != IW_MODE_INFRA &&
2927             ieee->reset_port &&
2928             ieee->reset_port(ieee->dev)) {
2929                 printk("reset_port failed\n");
2930                 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
2931                 return -EINVAL;
2932         }
2933 
2934         return ret;
2935 }
2936 
2937 static inline struct sk_buff *ieee80211_disassociate_skb(struct ieee80211_network *beacon,
2938                                                          struct ieee80211_device *ieee,
2939                                                          u8     asRsn)
2940 {
2941         struct sk_buff *skb;
2942         struct ieee80211_disassoc *disass;
2943 
2944         skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
2945         if (!skb)
2946                 return NULL;
2947 
2948         disass = skb_put(skb, sizeof(struct ieee80211_disassoc));
2949         disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
2950         disass->header.duration_id = 0;
2951 
2952         memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
2953         memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
2954         memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
2955 
2956         disass->reason = cpu_to_le16(asRsn);
2957         return skb;
2958 }
2959 
2960 void
2961 SendDisassociation(struct ieee80211_device *ieee,
2962                    u8                      *asSta,
2963                    u8                       asRsn
2964 )
2965 {
2966         struct ieee80211_network *beacon = &ieee->current_network;
2967         struct sk_buff *skb;
2968 
2969         skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
2970         if (skb) {
2971                 softmac_mgmt_xmit(skb, ieee);
2972                 //dev_kfree_skb_any(skb);//edit by thomas
2973         }
2974 }
2975 EXPORT_SYMBOL(SendDisassociation);
2976 
2977 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
2978 {
2979         struct ieee_param *param;
2980         int ret = 0;
2981 
2982         mutex_lock(&ieee->wx_mutex);
2983         //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
2984 
2985         if (p->length < sizeof(struct ieee_param) || !p->pointer) {
2986                 ret = -EINVAL;
2987                 goto out;
2988         }
2989 
2990         param = memdup_user(p->pointer, p->length);
2991         if (IS_ERR(param)) {
2992                 ret = PTR_ERR(param);
2993                 goto out;
2994         }
2995 
2996         switch (param->cmd) {
2997         case IEEE_CMD_SET_WPA_PARAM:
2998                 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
2999                                         param->u.wpa_param.value);
3000                 break;
3001 
3002         case IEEE_CMD_SET_WPA_IE:
3003                 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3004                 break;
3005 
3006         case IEEE_CMD_SET_ENCRYPTION:
3007                 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3008                 break;
3009 
3010         case IEEE_CMD_MLME:
3011                 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3012                                    param->u.mlme.reason_code);
3013                 break;
3014 
3015         default:
3016                 printk("Unknown WPA supplicant request: %d\n", param->cmd);
3017                 ret = -EOPNOTSUPP;
3018                 break;
3019         }
3020 
3021         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3022                 ret = -EFAULT;
3023 
3024         kfree(param);
3025 out:
3026         mutex_unlock(&ieee->wx_mutex);
3027 
3028         return ret;
3029 }
3030 EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3031 
3032 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3033 {
3034         union iwreq_data wrqu;
3035 
3036         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3037         if (ieee->state == IEEE80211_LINKED)
3038                 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3039         else
3040                 eth_zero_addr(wrqu.ap_addr.sa_data);
3041         wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3042 }
3043 EXPORT_SYMBOL(notify_wx_assoc_event);

/* [<][>][^][v][top][bottom][index][help] */