PageRenderTime 79ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 2ms

/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c

http://github.com/torvalds/linux
C | 5481 lines | 4066 code | 1060 blank | 355 comment | 900 complexity | 244f682d925e962db0cb8ae3051e2a80 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. // SPDX-License-Identifier: GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
  5. *
  6. ******************************************************************************/
  7. #define _RTW_MLME_EXT_C_
  8. #include <linux/ieee80211.h>
  9. #include <asm/unaligned.h>
  10. #include <osdep_service.h>
  11. #include <drv_types.h>
  12. #include <wifi.h>
  13. #include <rtw_mlme_ext.h>
  14. #include <wlan_bssdef.h>
  15. #include <mlme_osdep.h>
  16. #include <recv_osdep.h>
  17. static u8 null_addr[ETH_ALEN] = {};
  18. /**************************************************
  19. OUI definitions for the vendor specific IE
  20. ***************************************************/
  21. const u8 RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
  22. const u8 WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
  23. static const u8 WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
  24. static const u8 P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
  25. static const u8 WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  26. const u8 WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
  27. const u8 RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
  28. /********************************************************
  29. MCS rate definitions
  30. *********************************************************/
  31. const u8 MCS_rate_1R[16] = {
  32. 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  33. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  34. };
  35. /********************************************************
  36. ChannelPlan definitions
  37. *********************************************************/
  38. static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
  39. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
  40. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
  41. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
  42. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
  43. {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
  44. {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
  45. };
  46. static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
  47. /* 0x00 ~ 0x1F , Old Define ===== */
  48. {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
  49. {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
  50. {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
  51. {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
  52. {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
  53. {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
  54. {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
  55. {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
  56. {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
  57. {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
  58. {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
  59. {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
  60. {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
  61. {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
  62. {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
  63. {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
  64. {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
  65. {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
  66. {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
  67. {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
  68. {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
  69. {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
  70. {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
  71. {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
  72. {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
  73. {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
  74. {0x00}, /* 0x1A, */
  75. {0x00}, /* 0x1B, */
  76. {0x00}, /* 0x1C, */
  77. {0x00}, /* 0x1D, */
  78. {0x00}, /* 0x1E, */
  79. {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
  80. /* 0x20 ~ 0x7F , New Define ===== */
  81. {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
  82. {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
  83. {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
  84. {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
  85. {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
  86. {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
  87. {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
  88. {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
  89. {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
  90. {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
  91. {0x00}, /* 0x2A, */
  92. {0x00}, /* 0x2B, */
  93. {0x00}, /* 0x2C, */
  94. {0x00}, /* 0x2D, */
  95. {0x00}, /* 0x2E, */
  96. {0x00}, /* 0x2F, */
  97. {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
  98. {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
  99. {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
  100. {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
  101. {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
  102. {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
  103. {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
  104. {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
  105. {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
  106. {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
  107. {0x00}, /* 0x3A, */
  108. {0x00}, /* 0x3B, */
  109. {0x00}, /* 0x3C, */
  110. {0x00}, /* 0x3D, */
  111. {0x00}, /* 0x3E, */
  112. {0x00}, /* 0x3F, */
  113. {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
  114. {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
  115. };
  116. static const struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {
  117. 0x03
  118. }; /* use the combination for max channel numbers */
  119. /*
  120. * Search the @param channel_num in given @param channel_set
  121. * @ch_set: the given channel set
  122. * @ch: the given channel number
  123. *
  124. * return the index of channel_num in channel_set, -1 if not found
  125. */
  126. int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
  127. {
  128. int i;
  129. for (i = 0; ch_set[i].ChannelNum != 0; i++) {
  130. if (ch == ch_set[i].ChannelNum)
  131. break;
  132. }
  133. if (i >= ch_set[i].ChannelNum)
  134. return -1;
  135. return i;
  136. }
  137. struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
  138. {
  139. struct xmit_frame *pmgntframe;
  140. struct xmit_buf *pxmitbuf;
  141. pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
  142. if (!pmgntframe) {
  143. DBG_88E("%s, alloc xmitframe fail\n", __func__);
  144. return NULL;
  145. }
  146. pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
  147. if (!pxmitbuf) {
  148. DBG_88E("%s, alloc xmitbuf fail\n", __func__);
  149. rtw_free_xmitframe(pxmitpriv, pmgntframe);
  150. return NULL;
  151. }
  152. pmgntframe->frame_tag = MGNT_FRAMETAG;
  153. pmgntframe->pxmitbuf = pxmitbuf;
  154. pmgntframe->buf_addr = pxmitbuf->pbuf;
  155. pxmitbuf->priv_data = pmgntframe;
  156. return pmgntframe;
  157. }
  158. /****************************************************************************
  159. Following are some TX functions for WiFi MLME
  160. *****************************************************************************/
  161. void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
  162. {
  163. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  164. pmlmeext->tx_rate = rate;
  165. DBG_88E("%s(): rate = %x\n", __func__, rate);
  166. }
  167. void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
  168. {
  169. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  170. memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
  171. pattrib->hdrlen = 24;
  172. pattrib->nr_frags = 1;
  173. pattrib->priority = 7;
  174. pattrib->mac_id = 0;
  175. pattrib->qsel = 0x12;
  176. pattrib->pktlen = 0;
  177. if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
  178. pattrib->raid = 6;/* b mode */
  179. else
  180. pattrib->raid = 5;/* a/g mode */
  181. pattrib->encrypt = _NO_PRIVACY_;
  182. pattrib->bswenc = false;
  183. pattrib->qos_en = false;
  184. pattrib->ht_en = false;
  185. pattrib->bwmode = HT_CHANNEL_WIDTH_20;
  186. pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  187. pattrib->sgi = false;
  188. pattrib->seqnum = pmlmeext->mgnt_seq;
  189. pattrib->retry_ctrl = true;
  190. }
  191. static void dump_mgntframe(struct adapter *padapter,
  192. struct xmit_frame *pmgntframe)
  193. {
  194. if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
  195. return;
  196. rtw_hal_mgnt_xmit(padapter, pmgntframe);
  197. }
  198. static s32 dump_mgntframe_and_wait(struct adapter *padapter,
  199. struct xmit_frame *pmgntframe,
  200. int timeout_ms)
  201. {
  202. s32 ret = _FAIL;
  203. struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
  204. struct submit_ctx sctx;
  205. if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
  206. return ret;
  207. rtw_sctx_init(&sctx, timeout_ms);
  208. pxmitbuf->sctx = &sctx;
  209. ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
  210. if (ret == _SUCCESS)
  211. ret = rtw_sctx_wait(&sctx);
  212. return ret;
  213. }
  214. static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
  215. struct xmit_frame *pmgntframe)
  216. {
  217. s32 ret = _FAIL;
  218. u32 timeout_ms = 500;/* 500ms */
  219. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  220. if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
  221. return -1;
  222. if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
  223. return _FAIL;
  224. pxmitpriv->ack_tx = true;
  225. pmgntframe->ack_report = 1;
  226. if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
  227. ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
  228. pxmitpriv->ack_tx = false;
  229. mutex_unlock(&pxmitpriv->ack_tx_mutex);
  230. return ret;
  231. }
  232. static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
  233. {
  234. u8 *ssid_ie;
  235. uint ssid_len_ori;
  236. int len_diff = 0;
  237. ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
  238. if (ssid_ie && ssid_len_ori > 0) {
  239. switch (hidden_ssid_mode) {
  240. case 1: {
  241. u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
  242. u32 remain_len = 0;
  243. remain_len = ies_len - (next_ie - ies);
  244. ssid_ie[1] = 0;
  245. memcpy(ssid_ie + 2, next_ie, remain_len);
  246. len_diff -= ssid_len_ori;
  247. break;
  248. }
  249. case 2:
  250. memset(&ssid_ie[2], 0, ssid_len_ori);
  251. break;
  252. default:
  253. break;
  254. }
  255. }
  256. return len_diff;
  257. }
  258. static void issue_beacon(struct adapter *padapter, int timeout_ms)
  259. {
  260. struct xmit_frame *pmgntframe;
  261. struct pkt_attrib *pattrib;
  262. unsigned char *pframe;
  263. struct ieee80211_hdr *pwlanhdr;
  264. __le16 *fctrl;
  265. unsigned int rate_len;
  266. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  267. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  268. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  269. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  270. struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
  271. u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  272. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  273. if (!pmgntframe) {
  274. DBG_88E("%s, alloc mgnt frame fail\n", __func__);
  275. return;
  276. }
  277. #if defined(CONFIG_88EU_AP_MODE)
  278. spin_lock_bh(&pmlmepriv->bcn_update_lock);
  279. #endif
  280. /* update attribute */
  281. pattrib = &pmgntframe->attrib;
  282. update_mgntframe_attrib(padapter, pattrib);
  283. pattrib->qsel = 0x10;
  284. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  285. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  286. pwlanhdr = (struct ieee80211_hdr *)pframe;
  287. fctrl = &pwlanhdr->frame_control;
  288. *(fctrl) = 0;
  289. ether_addr_copy(pwlanhdr->addr1, bc_addr);
  290. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  291. ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
  292. SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
  293. /* pmlmeext->mgnt_seq++; */
  294. SetFrameSubType(pframe, WIFI_BEACON);
  295. pframe += sizeof(struct ieee80211_hdr_3addr);
  296. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  297. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  298. int len_diff;
  299. u8 *wps_ie;
  300. uint wps_ielen;
  301. u8 sr = 0;
  302. memcpy(pframe, cur_network->ies, cur_network->ie_length);
  303. len_diff = update_hidden_ssid(
  304. pframe + _BEACON_IE_OFFSET_
  305. , cur_network->ie_length - _BEACON_IE_OFFSET_
  306. , pmlmeinfo->hidden_ssid_mode
  307. );
  308. pframe += (cur_network->ie_length + len_diff);
  309. pattrib->pktlen += (cur_network->ie_length + len_diff);
  310. wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
  311. pattrib->pktlen - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
  312. if (wps_ie && wps_ielen > 0)
  313. rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
  314. if (sr != 0)
  315. set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
  316. else
  317. _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
  318. goto _issue_bcn;
  319. }
  320. /* below for ad-hoc mode */
  321. /* timestamp will be inserted by hardware */
  322. pframe += 8;
  323. pattrib->pktlen += 8;
  324. /* beacon interval: 2 bytes */
  325. memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
  326. pframe += 2;
  327. pattrib->pktlen += 2;
  328. /* capability info: 2 bytes */
  329. memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
  330. pframe += 2;
  331. pattrib->pktlen += 2;
  332. /* SSID */
  333. pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
  334. /* supported rates... */
  335. rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
  336. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
  337. /* DS parameter set */
  338. pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
  339. {
  340. u8 erpinfo = 0;
  341. u32 ATIMWindow;
  342. /* IBSS Parameter Set... */
  343. ATIMWindow = 0;
  344. pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
  345. /* ERP IE */
  346. pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
  347. }
  348. /* EXTERNDED SUPPORTED RATE */
  349. if (rate_len > 8)
  350. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
  351. /* todo:HT for adhoc */
  352. _issue_bcn:
  353. #if defined(CONFIG_88EU_AP_MODE)
  354. pmlmepriv->update_bcn = false;
  355. spin_unlock_bh(&pmlmepriv->bcn_update_lock);
  356. #endif
  357. if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
  358. DBG_88E("beacon frame too large\n");
  359. return;
  360. }
  361. pattrib->last_txcmdsz = pattrib->pktlen;
  362. /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
  363. if (timeout_ms > 0)
  364. dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
  365. else
  366. dump_mgntframe(padapter, pmgntframe);
  367. }
  368. static void issue_probersp(struct adapter *padapter, unsigned char *da)
  369. {
  370. struct xmit_frame *pmgntframe;
  371. struct pkt_attrib *pattrib;
  372. unsigned char *pframe;
  373. struct ieee80211_hdr *pwlanhdr;
  374. __le16 *fctrl;
  375. unsigned char *mac, *bssid;
  376. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  377. #if defined(CONFIG_88EU_AP_MODE)
  378. u8 *pwps_ie;
  379. uint wps_ielen;
  380. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  381. #endif
  382. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  383. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  384. struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
  385. unsigned int rate_len;
  386. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  387. if (!pmgntframe) {
  388. DBG_88E("%s, alloc mgnt frame fail\n", __func__);
  389. return;
  390. }
  391. /* update attribute */
  392. pattrib = &pmgntframe->attrib;
  393. update_mgntframe_attrib(padapter, pattrib);
  394. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  395. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  396. pwlanhdr = (struct ieee80211_hdr *)pframe;
  397. mac = myid(&padapter->eeprompriv);
  398. bssid = cur_network->MacAddress;
  399. fctrl = &pwlanhdr->frame_control;
  400. *(fctrl) = 0;
  401. ether_addr_copy(pwlanhdr->addr1, da);
  402. ether_addr_copy(pwlanhdr->addr2, mac);
  403. ether_addr_copy(pwlanhdr->addr3, bssid);
  404. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  405. pmlmeext->mgnt_seq++;
  406. SetFrameSubType(fctrl, WIFI_PROBERSP);
  407. pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
  408. pattrib->pktlen = pattrib->hdrlen;
  409. pframe += pattrib->hdrlen;
  410. if (cur_network->ie_length > MAX_IE_SZ)
  411. return;
  412. #if defined(CONFIG_88EU_AP_MODE)
  413. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  414. pwps_ie = rtw_get_wps_ie(cur_network->ies + _FIXED_IE_LENGTH_, cur_network->ie_length - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
  415. /* inerset & update wps_probe_resp_ie */
  416. if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
  417. uint wps_offset, remainder_ielen;
  418. u8 *premainder_ie;
  419. wps_offset = (uint)(pwps_ie - cur_network->ies);
  420. premainder_ie = pwps_ie + wps_ielen;
  421. remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
  422. memcpy(pframe, cur_network->ies, wps_offset);
  423. pframe += wps_offset;
  424. pattrib->pktlen += wps_offset;
  425. wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
  426. if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {
  427. memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);
  428. pframe += wps_ielen + 2;
  429. pattrib->pktlen += wps_ielen + 2;
  430. }
  431. if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
  432. memcpy(pframe, premainder_ie, remainder_ielen);
  433. pframe += remainder_ielen;
  434. pattrib->pktlen += remainder_ielen;
  435. }
  436. } else {
  437. memcpy(pframe, cur_network->ies, cur_network->ie_length);
  438. pframe += cur_network->ie_length;
  439. pattrib->pktlen += cur_network->ie_length;
  440. }
  441. } else
  442. #endif
  443. {
  444. /* timestamp will be inserted by hardware */
  445. pframe += 8;
  446. pattrib->pktlen += 8;
  447. /* beacon interval: 2 bytes */
  448. memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
  449. pframe += 2;
  450. pattrib->pktlen += 2;
  451. /* capability info: 2 bytes */
  452. memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
  453. pframe += 2;
  454. pattrib->pktlen += 2;
  455. /* below for ad-hoc mode */
  456. /* SSID */
  457. pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
  458. /* supported rates... */
  459. rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
  460. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
  461. /* DS parameter set */
  462. pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
  463. if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
  464. u8 erpinfo = 0;
  465. u32 ATIMWindow;
  466. /* IBSS Parameter Set... */
  467. /* ATIMWindow = cur->Configuration.ATIMWindow; */
  468. ATIMWindow = 0;
  469. pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
  470. /* ERP IE */
  471. pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
  472. }
  473. /* EXTERNDED SUPPORTED RATE */
  474. if (rate_len > 8)
  475. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
  476. /* todo:HT for adhoc */
  477. }
  478. pattrib->last_txcmdsz = pattrib->pktlen;
  479. dump_mgntframe(padapter, pmgntframe);
  480. }
  481. static int issue_probereq(struct adapter *padapter,
  482. struct ndis_802_11_ssid *pssid, u8 *da,
  483. bool wait_ack)
  484. {
  485. int ret = _FAIL;
  486. struct xmit_frame *pmgntframe;
  487. struct pkt_attrib *pattrib;
  488. unsigned char *pframe;
  489. struct ieee80211_hdr *pwlanhdr;
  490. __le16 *fctrl;
  491. unsigned char *mac;
  492. unsigned char bssrate[NumRates];
  493. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  494. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  495. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  496. int bssrate_len = 0;
  497. u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  498. RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__));
  499. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  500. if (!pmgntframe)
  501. goto exit;
  502. /* update attribute */
  503. pattrib = &pmgntframe->attrib;
  504. update_mgntframe_attrib(padapter, pattrib);
  505. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  506. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  507. pwlanhdr = (struct ieee80211_hdr *)pframe;
  508. mac = myid(&padapter->eeprompriv);
  509. fctrl = &pwlanhdr->frame_control;
  510. *(fctrl) = 0;
  511. if (da) {
  512. /* unicast probe request frame */
  513. ether_addr_copy(pwlanhdr->addr1, da);
  514. ether_addr_copy(pwlanhdr->addr3, da);
  515. } else {
  516. /* broadcast probe request frame */
  517. ether_addr_copy(pwlanhdr->addr1, bc_addr);
  518. ether_addr_copy(pwlanhdr->addr3, bc_addr);
  519. }
  520. ether_addr_copy(pwlanhdr->addr2, mac);
  521. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  522. pmlmeext->mgnt_seq++;
  523. SetFrameSubType(pframe, WIFI_PROBEREQ);
  524. pframe += sizeof(struct ieee80211_hdr_3addr);
  525. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  526. if (pssid)
  527. pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->ssid_length, pssid->ssid, &pattrib->pktlen);
  528. else
  529. pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen);
  530. get_rate_set(padapter, bssrate, &bssrate_len);
  531. if (bssrate_len > 8) {
  532. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
  533. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
  534. } else {
  535. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
  536. }
  537. /* add wps_ie for wps2.0 */
  538. if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
  539. memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
  540. pframe += pmlmepriv->wps_probe_req_ie_len;
  541. pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
  542. }
  543. pattrib->last_txcmdsz = pattrib->pktlen;
  544. RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
  545. ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
  546. if (wait_ack) {
  547. ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
  548. } else {
  549. dump_mgntframe(padapter, pmgntframe);
  550. ret = _SUCCESS;
  551. }
  552. exit:
  553. return ret;
  554. }
  555. static int issue_probereq_ex(struct adapter *padapter,
  556. struct ndis_802_11_ssid *pssid, u8 *da,
  557. int try_cnt, int wait_ms)
  558. {
  559. int ret;
  560. int i = 0;
  561. unsigned long start = jiffies;
  562. do {
  563. ret = issue_probereq(padapter, pssid, da, wait_ms > 0);
  564. i++;
  565. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  566. break;
  567. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  568. msleep(wait_ms);
  569. } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
  570. if (ret != _FAIL) {
  571. ret = _SUCCESS;
  572. goto exit;
  573. }
  574. if (try_cnt && wait_ms) {
  575. if (da)
  576. DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
  577. FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
  578. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  579. jiffies_to_msecs(jiffies - start));
  580. else
  581. DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
  582. FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
  583. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  584. jiffies_to_msecs(jiffies - start));
  585. }
  586. exit:
  587. return ret;
  588. }
  589. /* if psta == NULL, indicate we are station(client) now... */
  590. static void issue_auth(struct adapter *padapter, struct sta_info *psta,
  591. unsigned short status)
  592. {
  593. struct xmit_frame *pmgntframe;
  594. struct pkt_attrib *pattrib;
  595. unsigned char *pframe;
  596. struct ieee80211_hdr *pwlanhdr;
  597. __le16 *fctrl;
  598. unsigned int val32;
  599. u16 val16;
  600. #ifdef CONFIG_88EU_AP_MODE
  601. __le16 le_val16;
  602. #endif
  603. int use_shared_key = 0;
  604. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  605. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  606. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  607. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  608. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  609. if (!pmgntframe)
  610. return;
  611. /* update attribute */
  612. pattrib = &pmgntframe->attrib;
  613. update_mgntframe_attrib(padapter, pattrib);
  614. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  615. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  616. pwlanhdr = (struct ieee80211_hdr *)pframe;
  617. fctrl = &pwlanhdr->frame_control;
  618. *(fctrl) = 0;
  619. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  620. pmlmeext->mgnt_seq++;
  621. SetFrameSubType(pframe, WIFI_AUTH);
  622. pframe += sizeof(struct ieee80211_hdr_3addr);
  623. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  624. if (psta) {/* for AP mode */
  625. #ifdef CONFIG_88EU_AP_MODE
  626. ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
  627. ether_addr_copy(pwlanhdr->addr2,
  628. myid(&padapter->eeprompriv));
  629. ether_addr_copy(pwlanhdr->addr3,
  630. myid(&padapter->eeprompriv));
  631. /* setting auth algo number */
  632. val16 = (u16)psta->authalg;
  633. if (status != _STATS_SUCCESSFUL_)
  634. val16 = 0;
  635. if (val16) {
  636. le_val16 = cpu_to_le16(val16);
  637. use_shared_key = 1;
  638. } else {
  639. le_val16 = 0;
  640. }
  641. pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_val16,
  642. &pattrib->pktlen);
  643. /* setting auth seq number */
  644. val16 = (u16)psta->auth_seq;
  645. le_val16 = cpu_to_le16(val16);
  646. pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_val16,
  647. &pattrib->pktlen);
  648. /* setting status code... */
  649. val16 = status;
  650. le_val16 = cpu_to_le16(val16);
  651. pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_,
  652. &le_val16, &pattrib->pktlen);
  653. /* added challenging text... */
  654. if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
  655. pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &pattrib->pktlen);
  656. #endif
  657. } else {
  658. __le32 le_tmp32;
  659. __le16 le_tmp16;
  660. ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
  661. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  662. ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
  663. /* setting auth algo number */
  664. val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
  665. if (val16)
  666. use_shared_key = 1;
  667. /* setting IV for auth seq #3 */
  668. if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
  669. val32 = (pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30);
  670. le_tmp32 = cpu_to_le32(val32);
  671. pframe = rtw_set_fixed_ie(pframe, 4, &le_tmp32,
  672. &pattrib->pktlen);
  673. pattrib->iv_len = 4;
  674. }
  675. le_tmp16 = cpu_to_le16(val16);
  676. pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_tmp16,
  677. &pattrib->pktlen);
  678. /* setting auth seq number */
  679. val16 = pmlmeinfo->auth_seq;
  680. le_tmp16 = cpu_to_le16(val16);
  681. pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_tmp16,
  682. &pattrib->pktlen);
  683. /* setting status code... */
  684. le_tmp16 = cpu_to_le16(status);
  685. pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &le_tmp16,
  686. &pattrib->pktlen);
  687. /* then checking to see if sending challenging text... */
  688. if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
  689. pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &pattrib->pktlen);
  690. SetPrivacy(fctrl);
  691. pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
  692. pattrib->encrypt = _WEP40_;
  693. pattrib->icv_len = 4;
  694. pattrib->pktlen += pattrib->icv_len;
  695. }
  696. }
  697. pattrib->last_txcmdsz = pattrib->pktlen;
  698. rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
  699. DBG_88E("%s\n", __func__);
  700. dump_mgntframe(padapter, pmgntframe);
  701. }
  702. #ifdef CONFIG_88EU_AP_MODE
  703. static void issue_asocrsp(struct adapter *padapter, unsigned short status,
  704. struct sta_info *pstat, int pkt_type)
  705. {
  706. struct xmit_frame *pmgntframe;
  707. struct ieee80211_hdr *pwlanhdr;
  708. struct pkt_attrib *pattrib;
  709. unsigned char *pbuf, *pframe;
  710. unsigned short val;
  711. __le16 *fctrl;
  712. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  713. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  714. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  715. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  716. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  717. u8 *ie = pnetwork->ies;
  718. __le16 lestatus, leval;
  719. DBG_88E("%s\n", __func__);
  720. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  721. if (!pmgntframe)
  722. return;
  723. /* update attribute */
  724. pattrib = &pmgntframe->attrib;
  725. update_mgntframe_attrib(padapter, pattrib);
  726. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  727. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  728. pwlanhdr = (struct ieee80211_hdr *)pframe;
  729. fctrl = &pwlanhdr->frame_control;
  730. *(fctrl) = 0;
  731. ether_addr_copy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr);
  732. ether_addr_copy((void *)GetAddr2Ptr(pwlanhdr),
  733. myid(&padapter->eeprompriv));
  734. ether_addr_copy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress);
  735. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  736. pmlmeext->mgnt_seq++;
  737. if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
  738. SetFrameSubType(pwlanhdr, pkt_type);
  739. else
  740. return;
  741. pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
  742. pattrib->pktlen += pattrib->hdrlen;
  743. pframe += pattrib->hdrlen;
  744. /* capability */
  745. val = *(unsigned short *)rtw_get_capability_from_ie(ie);
  746. pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, &val, &pattrib->pktlen);
  747. lestatus = cpu_to_le16(status);
  748. pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &lestatus,
  749. &pattrib->pktlen);
  750. leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
  751. pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, &leval, &pattrib->pktlen);
  752. if (pstat->bssratelen <= 8) {
  753. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen);
  754. } else {
  755. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen);
  756. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen - 8, pstat->bssrateset + 8, &pattrib->pktlen);
  757. }
  758. if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
  759. uint ie_len = 0;
  760. /* FILL HT CAP INFO IE */
  761. pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
  762. if (pbuf && ie_len > 0) {
  763. memcpy(pframe, pbuf, ie_len + 2);
  764. pframe += (ie_len + 2);
  765. pattrib->pktlen += (ie_len + 2);
  766. }
  767. /* FILL HT ADD INFO IE */
  768. pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
  769. if (pbuf && ie_len > 0) {
  770. memcpy(pframe, pbuf, ie_len + 2);
  771. pframe += (ie_len + 2);
  772. pattrib->pktlen += (ie_len + 2);
  773. }
  774. }
  775. /* FILL WMM IE */
  776. if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
  777. uint ie_len = 0;
  778. unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  779. for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
  780. pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
  781. if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
  782. memcpy(pframe, pbuf, ie_len + 2);
  783. pframe += (ie_len + 2);
  784. pattrib->pktlen += (ie_len + 2);
  785. break;
  786. }
  787. if (!pbuf || ie_len == 0)
  788. break;
  789. }
  790. }
  791. if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
  792. pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
  793. /* add WPS IE ie for wps 2.0 */
  794. if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
  795. memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
  796. pframe += pmlmepriv->wps_assoc_resp_ie_len;
  797. pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
  798. }
  799. pattrib->last_txcmdsz = pattrib->pktlen;
  800. dump_mgntframe(padapter, pmgntframe);
  801. }
  802. #endif /* CONFIG_88EU_AP_MODE */
  803. static void issue_assocreq(struct adapter *padapter)
  804. {
  805. int ret = _FAIL;
  806. struct xmit_frame *pmgntframe;
  807. struct pkt_attrib *pattrib;
  808. unsigned char *pframe, *p;
  809. struct ieee80211_hdr *pwlanhdr;
  810. __le16 *fctrl;
  811. unsigned int i, j, ie_len, index = 0;
  812. unsigned char bssrate[NumRates], sta_bssrate[NumRates];
  813. struct ndis_802_11_var_ie *pIE;
  814. struct registry_priv *pregpriv = &padapter->registrypriv;
  815. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  816. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  817. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  818. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  819. int bssrate_len = 0, sta_bssrate_len = 0;
  820. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  821. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  822. if (!pmgntframe)
  823. goto exit;
  824. /* update attribute */
  825. pattrib = &pmgntframe->attrib;
  826. update_mgntframe_attrib(padapter, pattrib);
  827. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  828. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  829. pwlanhdr = (struct ieee80211_hdr *)pframe;
  830. fctrl = &pwlanhdr->frame_control;
  831. *(fctrl) = 0;
  832. ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
  833. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  834. ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
  835. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  836. pmlmeext->mgnt_seq++;
  837. SetFrameSubType(pframe, WIFI_ASSOCREQ);
  838. pframe += sizeof(struct ieee80211_hdr_3addr);
  839. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  840. /* caps */
  841. memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
  842. pframe += 2;
  843. pattrib->pktlen += 2;
  844. /* listen interval */
  845. /* todo: listen interval for power saving */
  846. put_unaligned_le16(3, pframe);
  847. pframe += 2;
  848. pattrib->pktlen += 2;
  849. /* SSID */
  850. pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &pattrib->pktlen);
  851. /* supported rate & extended supported rate */
  852. /* Check if the AP's supported rates are also supported by STA. */
  853. get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
  854. if (pmlmeext->cur_channel == 14)/* for JAPAN, channel 14 can only uses B Mode(CCK) */
  855. sta_bssrate_len = 4;
  856. for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
  857. if (pmlmeinfo->network.SupportedRates[i] == 0)
  858. break;
  859. DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
  860. }
  861. for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
  862. if (pmlmeinfo->network.SupportedRates[i] == 0)
  863. break;
  864. /* Check if the AP's supported rates are also supported by STA. */
  865. for (j = 0; j < sta_bssrate_len; j++) {
  866. /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
  867. if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
  868. == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
  869. break;
  870. }
  871. if (j == sta_bssrate_len) {
  872. /* the rate is not supported by STA */
  873. DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
  874. } else {
  875. /* the rate is supported by STA */
  876. bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
  877. }
  878. }
  879. bssrate_len = index;
  880. DBG_88E("bssrate_len=%d\n", bssrate_len);
  881. if (bssrate_len == 0) {
  882. rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
  883. rtw_free_xmitframe(pxmitpriv, pmgntframe);
  884. goto exit; /* don't connect to AP if no joint supported rate */
  885. }
  886. if (bssrate_len > 8) {
  887. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
  888. pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
  889. } else {
  890. pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
  891. }
  892. /* RSN */
  893. p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
  894. if (p)
  895. pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, p + 2, &pattrib->pktlen);
  896. /* HT caps */
  897. if (padapter->mlmepriv.htpriv.ht_option) {
  898. p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
  899. if (p && !is_ap_in_tkip(padapter)) {
  900. memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap));
  901. /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
  902. if (pregpriv->cbw40_enable == 0)
  903. pmlmeinfo->HT_caps.cap_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
  904. else
  905. pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(BIT(1));
  906. /* todo: disable SM power save mode */
  907. pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x000c);
  908. if (pregpriv->rx_stbc)
  909. pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
  910. memcpy((u8 *)&pmlmeinfo->HT_caps.mcs, MCS_rate_1R, 16);
  911. pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen);
  912. }
  913. }
  914. /* vendor specific IE, such as WPA, WMM, WPS */
  915. for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length; i += (pIE->Length + 2)) {
  916. pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
  917. switch (pIE->ElementID) {
  918. case _VENDOR_SPECIFIC_IE_:
  919. if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
  920. (!memcmp(pIE->data, WMM_OUI, 4)) ||
  921. (!memcmp(pIE->data, WPS_OUI, 4))) {
  922. if (!padapter->registrypriv.wifi_spec) {
  923. /* Commented by Kurt 20110629 */
  924. /* In some older APs, WPS handshake */
  925. /* would be fail if we append vender extensions information to AP */
  926. if (!memcmp(pIE->data, WPS_OUI, 4))
  927. pIE->Length = 14;
  928. }
  929. pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &pattrib->pktlen);
  930. }
  931. break;
  932. default:
  933. break;
  934. }
  935. }
  936. if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
  937. pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
  938. pattrib->last_txcmdsz = pattrib->pktlen;
  939. dump_mgntframe(padapter, pmgntframe);
  940. ret = _SUCCESS;
  941. exit:
  942. if (ret == _SUCCESS)
  943. rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
  944. else
  945. rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
  946. }
  947. /* when wait_ack is true, this function should be called at process context */
  948. static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
  949. unsigned int power_mode, bool wait_ack)
  950. {
  951. int ret = _FAIL;
  952. struct xmit_frame *pmgntframe;
  953. struct pkt_attrib *pattrib;
  954. unsigned char *pframe;
  955. struct ieee80211_hdr *pwlanhdr;
  956. __le16 *fctrl;
  957. struct xmit_priv *pxmitpriv;
  958. struct mlme_ext_priv *pmlmeext;
  959. struct mlme_ext_info *pmlmeinfo;
  960. struct wlan_bssid_ex *pnetwork;
  961. if (!padapter)
  962. goto exit;
  963. pxmitpriv = &padapter->xmitpriv;
  964. pmlmeext = &padapter->mlmeextpriv;
  965. pmlmeinfo = &pmlmeext->mlmext_info;
  966. pnetwork = &pmlmeinfo->network;
  967. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  968. if (!pmgntframe)
  969. goto exit;
  970. /* update attribute */
  971. pattrib = &pmgntframe->attrib;
  972. update_mgntframe_attrib(padapter, pattrib);
  973. pattrib->retry_ctrl = false;
  974. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  975. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  976. pwlanhdr = (struct ieee80211_hdr *)pframe;
  977. fctrl = &pwlanhdr->frame_control;
  978. *(fctrl) = 0;
  979. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
  980. SetFrDs(fctrl);
  981. else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
  982. SetToDs(fctrl);
  983. if (power_mode)
  984. SetPwrMgt(fctrl);
  985. ether_addr_copy(pwlanhdr->addr1, da);
  986. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  987. ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
  988. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  989. pmlmeext->mgnt_seq++;
  990. SetFrameSubType(pframe, WIFI_DATA_NULL);
  991. pframe += sizeof(struct ieee80211_hdr_3addr);
  992. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  993. pattrib->last_txcmdsz = pattrib->pktlen;
  994. if (wait_ack) {
  995. ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
  996. } else {
  997. dump_mgntframe(padapter, pmgntframe);
  998. ret = _SUCCESS;
  999. }
  1000. exit:
  1001. return ret;
  1002. }
  1003. /* when wait_ms > 0 , this function should be called at process context */
  1004. /* da == NULL for station mode */
  1005. int issue_nulldata(struct adapter *padapter, unsigned char *da,
  1006. unsigned int power_mode, int try_cnt, int wait_ms)
  1007. {
  1008. int ret;
  1009. int i = 0;
  1010. unsigned long start = jiffies;
  1011. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1012. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1013. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  1014. /* da == NULL, assume it's null data for sta to ap*/
  1015. if (!da)
  1016. da = pnetwork->MacAddress;
  1017. do {
  1018. ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
  1019. i++;
  1020. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  1021. break;
  1022. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  1023. msleep(wait_ms);
  1024. } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
  1025. if (ret != _FAIL) {
  1026. ret = _SUCCESS;
  1027. goto exit;
  1028. }
  1029. if (try_cnt && wait_ms) {
  1030. if (da)
  1031. DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
  1032. FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
  1033. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  1034. jiffies_to_msecs(jiffies - start));
  1035. else
  1036. DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
  1037. FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
  1038. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  1039. jiffies_to_msecs(jiffies - start));
  1040. }
  1041. exit:
  1042. return ret;
  1043. }
  1044. /* when wait_ack is true, this function should be called at process context */
  1045. static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
  1046. u16 tid, bool wait_ack)
  1047. {
  1048. int ret = _FAIL;
  1049. struct xmit_frame *pmgntframe;
  1050. struct pkt_attrib *pattrib;
  1051. unsigned char *pframe;
  1052. struct ieee80211_hdr *pwlanhdr;
  1053. __le16 *fctrl;
  1054. unsigned short *qc;
  1055. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1056. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1057. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1058. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  1059. DBG_88E("%s\n", __func__);
  1060. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1061. if (!pmgntframe)
  1062. goto exit;
  1063. /* update attribute */
  1064. pattrib = &pmgntframe->attrib;
  1065. update_mgntframe_attrib(padapter, pattrib);
  1066. pattrib->hdrlen += 2;
  1067. pattrib->qos_en = true;
  1068. pattrib->eosp = 1;
  1069. pattrib->ack_policy = 0;
  1070. pattrib->mdata = 0;
  1071. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  1072. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  1073. pwlanhdr = (struct ieee80211_hdr *)pframe;
  1074. fctrl = &pwlanhdr->frame_control;
  1075. *(fctrl) = 0;
  1076. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
  1077. SetFrDs(fctrl);
  1078. else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
  1079. SetToDs(fctrl);
  1080. if (pattrib->mdata)
  1081. SetMData(fctrl);
  1082. qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
  1083. SetPriority(qc, tid);
  1084. SetEOSP(qc, pattrib->eosp);
  1085. SetAckpolicy(qc, pattrib->ack_policy);
  1086. ether_addr_copy(pwlanhdr->addr1, da);
  1087. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  1088. ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
  1089. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  1090. pmlmeext->mgnt_seq++;
  1091. SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
  1092. pframe += sizeof(struct ieee80211_qos_hdr);
  1093. pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
  1094. pattrib->last_txcmdsz = pattrib->pktlen;
  1095. if (wait_ack) {
  1096. ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
  1097. } else {
  1098. dump_mgntframe(padapter, pmgntframe);
  1099. ret = _SUCCESS;
  1100. }
  1101. exit:
  1102. return ret;
  1103. }
  1104. /* when wait_ms > 0 , this function should be called at process context */
  1105. /* da == NULL for station mode */
  1106. int issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
  1107. u16 tid, int try_cnt, int wait_ms)
  1108. {
  1109. int ret;
  1110. int i = 0;
  1111. unsigned long start = jiffies;
  1112. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1113. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1114. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  1115. /* da == NULL, assume it's null data for sta to ap*/
  1116. if (!da)
  1117. da = pnetwork->MacAddress;
  1118. do {
  1119. ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
  1120. i++;
  1121. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  1122. break;
  1123. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  1124. msleep(wait_ms);
  1125. } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
  1126. if (ret != _FAIL) {
  1127. ret = _SUCCESS;
  1128. goto exit;
  1129. }
  1130. if (try_cnt && wait_ms) {
  1131. if (da)
  1132. DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
  1133. FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
  1134. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  1135. jiffies_to_msecs(jiffies - start));
  1136. else
  1137. DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
  1138. FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
  1139. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  1140. jiffies_to_msecs(jiffies - start));
  1141. }
  1142. exit:
  1143. return ret;
  1144. }
  1145. static int _issue_deauth(struct adapter *padapter, unsigned char *da,
  1146. unsigned short reason, bool wait_ack)
  1147. {
  1148. struct xmit_frame *pmgntframe;
  1149. struct pkt_attrib *pattrib;
  1150. unsigned char *pframe;
  1151. struct ieee80211_hdr *pwlanhdr;
  1152. __le16 *fctrl;
  1153. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1154. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1155. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1156. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  1157. int ret = _FAIL;
  1158. __le16 le_tmp;
  1159. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1160. if (!pmgntframe)
  1161. goto exit;
  1162. /* update attribute */
  1163. pattrib = &pmgntframe->attrib;
  1164. update_mgntframe_attrib(padapter, pattrib);
  1165. pattrib->retry_ctrl = false;
  1166. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  1167. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  1168. pwlanhdr = (struct ieee80211_hdr *)pframe;
  1169. fctrl = &pwlanhdr->frame_control;
  1170. *(fctrl) = 0;
  1171. ether_addr_copy(pwlanhdr->addr1, da);
  1172. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  1173. ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
  1174. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  1175. pmlmeext->mgnt_seq++;
  1176. SetFrameSubType(pframe, WIFI_DEAUTH);
  1177. pframe += sizeof(struct ieee80211_hdr_3addr);
  1178. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  1179. le_tmp = cpu_to_le16(reason);
  1180. pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, &le_tmp,
  1181. &pattrib->pktlen);
  1182. pattrib->last_txcmdsz = pattrib->pktlen;
  1183. if (wait_ack) {
  1184. ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
  1185. } else {
  1186. dump_mgntframe(padapter, pmgntframe);
  1187. ret = _SUCCESS;
  1188. }
  1189. exit:
  1190. return ret;
  1191. }
  1192. int issue_deauth(struct adapter *padapter, unsigned char *da,
  1193. unsigned short reason)
  1194. {
  1195. DBG_88E("%s to %pM\n", __func__, da);
  1196. return _issue_deauth(padapter, da, reason, false);
  1197. }
  1198. static int issue_deauth_ex(struct adapter *padapter, u8 *da,
  1199. unsigned short reason, int try_cnt,
  1200. int wait_ms)
  1201. {
  1202. int ret;
  1203. int i = 0;
  1204. unsigned long start = jiffies;
  1205. do {
  1206. ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
  1207. i++;
  1208. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  1209. break;
  1210. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  1211. mdelay(wait_ms);
  1212. } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
  1213. if (ret != _FAIL) {
  1214. ret = _SUCCESS;
  1215. goto exit;
  1216. }
  1217. if (try_cnt && wait_ms) {
  1218. if (da)
  1219. DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
  1220. FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
  1221. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  1222. jiffies_to_msecs(jiffies - start));
  1223. else
  1224. DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
  1225. FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
  1226. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  1227. jiffies_to_msecs(jiffies - start));
  1228. }
  1229. exit:
  1230. return ret;
  1231. }
  1232. static void issue_action_BA(struct adapter *padapter, unsigned char *raddr,
  1233. unsigned char action, unsigned short status)
  1234. {
  1235. u8 category = RTW_WLAN_CATEGORY_BACK;
  1236. u16 start_seq;
  1237. u16 BA_para_set;
  1238. u16 reason_code;
  1239. u16 BA_timeout_value;
  1240. __le16 le_tmp;
  1241. u16 BA_starting_seqctrl = 0;
  1242. enum ht_cap_ampdu_factor max_rx_ampdu_factor;
  1243. struct xmit_frame *pmgntframe;
  1244. struct pkt_attrib *pattrib;
  1245. u8 *pframe;
  1246. struct ieee80211_hdr *pwlanhdr;
  1247. __le16 *fctrl;
  1248. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1249. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1250. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1251. struct sta_info *psta;
  1252. struct sta_priv *pstapriv = &padapter->stapriv;
  1253. struct registry_priv *pregpriv = &padapter->registrypriv;
  1254. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  1255. DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
  1256. pmgntframe = alloc_mgtxmitframe(pxmitpriv);
  1257. if (!pmgntframe)
  1258. return;
  1259. /* update attribute */
  1260. pattrib = &pmgntframe->attrib;
  1261. update_mgntframe_attrib(padapter, pattrib);
  1262. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  1263. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  1264. pwlanhdr = (struct ieee80211_hdr *)pframe;
  1265. fctrl = &pwlanhdr->frame_control;
  1266. *(fctrl) = 0;
  1267. ether_addr_copy(pwlanhdr->addr1, raddr);
  1268. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  1269. ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
  1270. SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
  1271. pmlmeext->mgnt_seq++;
  1272. SetFrameSubType(pframe, WIFI_ACTION);
  1273. pframe += sizeof(struct ieee80211_hdr_3addr);
  1274. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  1275. pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
  1276. pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
  1277. if (category == 3) {
  1278. switch (action) {
  1279. case 0: /* ADDBA req */
  1280. do {
  1281. pmlmeinfo->dialogToken++;
  1282. } while (pmlmeinfo->dialogToken == 0);
  1283. pframe = rtw_set_fixed_ie(pframe, 1, &pmlmeinfo->dialogToken, &pattrib->pktlen);
  1284. BA_para_set = 0x1002 | ((status & 0xf) << 2); /* immediate ack & 64 buffer size */
  1285. le_tmp = cpu_to_le16(BA_para_set);
  1286. pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
  1287. &pattrib->pktlen);
  1288. BA_timeout_value = 5000;/* 5ms */
  1289. le_tmp = cpu_to_le16(BA_timeout_value);
  1290. pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
  1291. &pattrib->pktlen);
  1292. psta = rtw_get_stainfo(pstapriv, raddr);
  1293. if (psta) {
  1294. start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1;
  1295. DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
  1296. psta->BA_starting_seqctrl[status & 0x07] = start_seq;
  1297. BA_starting_seqctrl = start_seq << 4;
  1298. }
  1299. le_tmp = cpu_to_le16(BA_starting_seqctrl);
  1300. pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
  1301. &pattrib->pktlen);
  1302. break;
  1303. case 1: /* ADDBA rsp */
  1304. {
  1305. struct ADDBA_request *ADDBA_req = &pmlmeinfo->ADDBA_req;
  1306. pframe = rtw_set_fixed_ie(pframe, 1,
  1307. &ADDBA_req->dialog_token,
  1308. &pattrib->pktlen);
  1309. pframe = rtw_set_fixed_ie(pframe, 2, &status,
  1310. &pattrib->pktlen);
  1311. BA_para_set = le16_to_cpu(ADDBA_req->BA_para_set) &
  1312. 0x3f;
  1313. rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
  1314. switch (max_rx_ampdu_factor) {
  1315. case MAX_AMPDU_FACTOR_64K:
  1316. BA_para_set |= 0x1000; /* 64 buffer size */
  1317. break;
  1318. case MAX_AMPDU_FACTOR_32K:
  1319. BA_para_set |= 0x0800; /* 32 buffer size */
  1320. break;
  1321. case MAX_AMPDU_FACTOR_16K:
  1322. BA_para_set |= 0x0400; /* 16 buffer size */
  1323. break;
  1324. case MAX_AMPDU_FACTOR_8K:
  1325. BA_para_set |= 0x0200; /* 8 buffer size */
  1326. break;
  1327. default:
  1328. BA_para_set |= 0x1000; /* 64 buffer size */
  1329. break;
  1330. }
  1331. if (pregpriv->ampdu_amsdu == 0)/* disabled */
  1332. BA_para_set = BA_para_set & ~BIT(0);
  1333. else if (pregpriv->ampdu_amsdu == 1)/* enabled */
  1334. BA_para_set = BA_para_set | BIT(0);
  1335. le_tmp = cpu_to_le16(BA_para_set);
  1336. pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
  1337. &pattrib->pktlen);
  1338. pframe = rtw_set_fixed_

Large files files are truncated, but you can click here to view the full file