PageRenderTime 90ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/staging/rtl8723au/core/rtw_mlme_ext.c

http://github.com/mirrors/linux-2.6
C | 6187 lines | 4556 code | 1132 blank | 499 comment | 894 complexity | eadf830d0512b176f49eec5fbcf30820 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. ******************************************************************************/
  15. #define _RTW_MLME_EXT_C_
  16. #include <osdep_service.h>
  17. #include <drv_types.h>
  18. #include <wifi.h>
  19. #include <rtw_mlme_ext.h>
  20. #include <wlan_bssdef.h>
  21. #include <mlme_osdep.h>
  22. #include <recv_osdep.h>
  23. #include <linux/ieee80211.h>
  24. #include <rtl8723a_hal.h>
  25. static int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  26. static int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  27. static int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  28. static int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  29. static int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  30. static int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  31. static int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  32. static int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  33. static int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  34. static int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  35. static int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  36. static int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  37. static int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  38. static int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  39. static int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  40. static int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  41. static int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  42. static int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  43. static int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  44. static void issue_assocreq(struct rtw_adapter *padapter);
  45. static void issue_probereq(struct rtw_adapter *padapter,
  46. struct cfg80211_ssid *pssid, u8 *da);
  47. static int issue_probereq_ex(struct rtw_adapter *padapter,
  48. struct cfg80211_ssid *pssid,
  49. u8 *da, int try_cnt, int wait_ms);
  50. static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da);
  51. static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
  52. unsigned short status);
  53. static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
  54. unsigned short reason, int try_cnt, int wait_ms);
  55. static void start_clnt_assoc(struct rtw_adapter *padapter);
  56. static void start_clnt_auth(struct rtw_adapter *padapter);
  57. static void start_clnt_join(struct rtw_adapter *padapter);
  58. static void start_create_ibss(struct rtw_adapter *padapter);
  59. static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
  60. struct recv_frame *precv_frame);
  61. #ifdef CONFIG_8723AU_AP_MODE
  62. static int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
  63. static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
  64. struct sta_info *pstat, u16 pkt_type);
  65. #endif
  66. static struct mlme_handler mlme_sta_tbl[]={
  67. {"OnAssocReq23a", &OnAssocReq23a},
  68. {"OnAssocRsp23a", &OnAssocRsp23a},
  69. {"OnReAssocReq", &OnAssocReq23a},
  70. {"OnReAssocRsp", &OnAssocRsp23a},
  71. {"OnProbeReq23a", &OnProbeReq23a},
  72. {"OnProbeRsp23a", &OnProbeRsp23a},
  73. /*----------------------------------------------------------
  74. below 2 are reserved
  75. -----------------------------------------------------------*/
  76. {"DoReserved23a", &DoReserved23a},
  77. {"DoReserved23a", &DoReserved23a},
  78. {"OnBeacon23a", &OnBeacon23a},
  79. {"OnATIM", &OnAtim23a},
  80. {"OnDisassoc23a", &OnDisassoc23a},
  81. {"OnAuth23a", &OnAuth23aClient23a},
  82. {"OnDeAuth23a", &OnDeAuth23a},
  83. {"OnAction23a", &OnAction23a},
  84. };
  85. static struct action_handler OnAction23a_tbl[]={
  86. {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
  87. {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
  88. {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
  89. {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
  90. {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
  91. {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
  92. {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
  93. {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
  94. {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
  95. };
  96. static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
  97. /**************************************************
  98. OUI definitions for the vendor specific IE
  99. ***************************************************/
  100. unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
  101. unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
  102. unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
  103. unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
  104. unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
  105. unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  106. static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
  107. /********************************************************
  108. MCS rate definitions
  109. *********************************************************/
  110. unsigned char MCS_rate_2R23A[16] = {
  111. 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
  112. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
  113. unsigned char MCS_rate_1R23A[16] = {
  114. 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0,
  115. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
  116. /********************************************************
  117. ChannelPlan definitions
  118. *********************************************************/
  119. static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
  120. /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
  121. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
  122. /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
  123. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
  124. /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
  125. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
  126. /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
  127. {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
  128. /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
  129. {{10, 11, 12, 13}, 4},
  130. /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
  131. {{}, 0},
  132. };
  133. static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
  134. /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
  135. {{}, 0},
  136. /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
  137. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  138. 116, 120, 124, 128, 132, 136, 140}, 19},
  139. /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
  140. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  141. 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
  142. /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
  143. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  144. 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
  145. /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
  146. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  147. 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
  148. /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
  149. {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
  150. /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
  151. {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
  152. /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
  153. {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
  154. /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
  155. {{149, 153, 157, 161, 165}, 5},
  156. /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
  157. {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
  158. /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
  159. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  160. 116, 136, 140, 149, 153, 157, 161, 165}, 20},
  161. /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
  162. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  163. 116, 120, 124, 149, 153, 157, 161, 165}, 20},
  164. /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
  165. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  166. 116, 120, 124, 128, 132, 136, 140}, 19},
  167. /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
  168. {{36, 40, 44, 48, 52, 56, 60, 64}, 8},
  169. /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
  170. {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
  171. /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
  172. {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149,
  173. 153, 157, 161, 165}, 15},
  174. /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
  175. {{56, 60, 64, 149, 153, 157, 161, 165}, 8},
  176. /* Driver self defined for old channel plan Compatible,
  177. Remember to modify if have new channel plan definition ===== */
  178. /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */
  179. {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112,
  180. 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
  181. /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
  182. {{36, 40, 44, 48}, 4},
  183. /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
  184. {{36, 40, 44, 48, 149, 153, 157, 161}, 8},
  185. };
  186. static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
  187. /* 0x00 ~ 0x1F , Old Define ===== */
  188. {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
  189. {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
  190. {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
  191. {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
  192. {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
  193. {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
  194. {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
  195. {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
  196. {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
  197. {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
  198. {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
  199. {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
  200. {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
  201. {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
  202. {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
  203. {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
  204. {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
  205. {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
  206. {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
  207. {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
  208. {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
  209. {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
  210. {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
  211. {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
  212. {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
  213. {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
  214. {0x00, 0x00}, /* 0x1A, */
  215. {0x00, 0x00}, /* 0x1B, */
  216. {0x00, 0x00}, /* 0x1C, */
  217. {0x00, 0x00}, /* 0x1D, */
  218. {0x00, 0x00}, /* 0x1E, */
  219. {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
  220. /* 0x20 ~ 0x7F , New Define ===== */
  221. {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
  222. {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
  223. {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
  224. {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
  225. {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
  226. {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
  227. {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
  228. {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
  229. {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
  230. {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
  231. {0x00, 0x00}, /* 0x2A, */
  232. {0x00, 0x00}, /* 0x2B, */
  233. {0x00, 0x00}, /* 0x2C, */
  234. {0x00, 0x00}, /* 0x2D, */
  235. {0x00, 0x00}, /* 0x2E, */
  236. {0x00, 0x00}, /* 0x2F, */
  237. {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
  238. {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
  239. {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
  240. {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
  241. {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
  242. {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
  243. {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
  244. {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
  245. {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
  246. {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
  247. {0x00, 0x00}, /* 0x3A, */
  248. {0x00, 0x00}, /* 0x3B, */
  249. {0x00, 0x00}, /* 0x3C, */
  250. {0x00, 0x00}, /* 0x3D, */
  251. {0x00, 0x00}, /* 0x3E, */
  252. {0x00, 0x00}, /* 0x3F, */
  253. {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
  254. {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
  255. };
  256. static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE =
  257. {0x03, 0x02}; /* use the conbination for max channel numbers */
  258. static void dummy_event_callback(struct rtw_adapter *adapter, const u8 *pbuf)
  259. {
  260. }
  261. static struct fwevent wlanevents[] =
  262. {
  263. {0, &dummy_event_callback}, /*0*/
  264. {0, NULL},
  265. {0, NULL},
  266. {0, NULL},
  267. {0, NULL},
  268. {0, NULL},
  269. {0, NULL},
  270. {0, NULL},
  271. {0, &rtw_survey_event_cb23a}, /*8*/
  272. {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a},
  273. {0, &rtw23a_joinbss_event_cb}, /*10*/
  274. {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
  275. {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
  276. {0, &dummy_event_callback},
  277. {0, &dummy_event_callback},
  278. {0, NULL}, /*15*/
  279. {0, NULL},
  280. {0, NULL},
  281. {0, NULL},
  282. {0, &dummy_event_callback},
  283. {0, NULL}, /*20*/
  284. {0, NULL},
  285. {0, NULL},
  286. {0, &dummy_event_callback},
  287. {0, NULL},
  288. };
  289. static void rtw_correct_TSF(struct rtw_adapter *padapter)
  290. {
  291. hw_var_set_correct_tsf(padapter);
  292. }
  293. static void
  294. rtw_update_TSF(struct mlme_ext_priv *pmlmeext, struct ieee80211_mgmt *mgmt)
  295. {
  296. pmlmeext->TSFValue = get_unaligned_le64(&mgmt->u.beacon.timestamp);
  297. }
  298. /*
  299. * Search the @param channel_num in given @param channel_set
  300. * @ch_set: the given channel set
  301. * @ch: the given channel number
  302. *
  303. * return the index of channel_num in channel_set, -1 if not found
  304. */
  305. int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
  306. {
  307. int i;
  308. for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
  309. if (ch == ch_set[i].ChannelNum)
  310. break;
  311. }
  312. if (i >= ch_set[i].ChannelNum)
  313. return -1;
  314. return i;
  315. }
  316. /****************************************************************************
  317. Following are the initialization functions for WiFi MLME
  318. *****************************************************************************/
  319. int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
  320. {
  321. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  322. set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
  323. pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
  324. return _SUCCESS;
  325. }
  326. static void init_mlme_ext_priv23a_value(struct rtw_adapter *padapter)
  327. {
  328. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  329. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  330. unsigned char mixed_datarate[NumRates] = {
  331. _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
  332. _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
  333. _48M_RATE_, _54M_RATE_, 0xff};
  334. unsigned char mixed_basicrate[NumRates] = {
  335. _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
  336. _12M_RATE_, _24M_RATE_, 0xff,};
  337. atomic_set(&pmlmeext->event_seq, 0);
  338. /* reset to zero when disconnect at client mode */
  339. pmlmeext->mgnt_seq = 0;
  340. pmlmeext->cur_channel = padapter->registrypriv.channel;
  341. pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
  342. pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  343. pmlmeext->retry = 0;
  344. pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
  345. memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
  346. memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
  347. if (pmlmeext->cur_channel > 14)
  348. pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
  349. else
  350. pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
  351. pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
  352. pmlmeext->sitesurvey_res.channel_idx = 0;
  353. pmlmeext->sitesurvey_res.bss_cnt = 0;
  354. pmlmeext->scan_abort = false;
  355. pmlmeinfo->state = MSR_NOLINK;
  356. pmlmeinfo->reauth_count = 0;
  357. pmlmeinfo->reassoc_count = 0;
  358. pmlmeinfo->link_count = 0;
  359. pmlmeinfo->auth_seq = 0;
  360. pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
  361. pmlmeinfo->key_index = 0;
  362. pmlmeinfo->iv = 0;
  363. pmlmeinfo->enc_algo = 0;
  364. pmlmeinfo->authModeToggle = 0;
  365. memset(pmlmeinfo->chg_txt, 0, 128);
  366. pmlmeinfo->slotTime = SHORT_SLOT_TIME;
  367. pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
  368. pmlmeinfo->dialogToken = 0;
  369. pmlmeext->action_public_rxseq = 0xffff;
  370. pmlmeext->action_public_dialog_token = 0xff;
  371. }
  372. static int has_channel(struct rt_channel_info *channel_set,
  373. u8 chanset_size, u8 chan) {
  374. int i;
  375. for (i = 0; i < chanset_size; i++) {
  376. if (channel_set[i].ChannelNum == chan)
  377. return 1;
  378. }
  379. return 0;
  380. }
  381. static void init_channel_list(struct rtw_adapter *padapter,
  382. struct rt_channel_info *channel_set,
  383. u8 chanset_size,
  384. struct p2p_channels *channel_list)
  385. {
  386. struct p2p_oper_class_map op_class[] = {
  387. { IEEE80211G, 81, 1, 13, 1, BW20 },
  388. { IEEE80211G, 82, 14, 14, 1, BW20 },
  389. { IEEE80211A, 115, 36, 48, 4, BW20 },
  390. { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
  391. { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
  392. { IEEE80211A, 124, 149, 161, 4, BW20 },
  393. { IEEE80211A, 125, 149, 169, 4, BW20 },
  394. { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
  395. { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
  396. { -1, 0, 0, 0, 0, BW20 }
  397. };
  398. int cla, op;
  399. cla = 0;
  400. for (op = 0; op_class[op].op_class; op++) {
  401. u8 ch;
  402. struct p2p_oper_class_map *o = &op_class[op];
  403. struct p2p_reg_class *reg = NULL;
  404. for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
  405. if (!has_channel(channel_set, chanset_size, ch))
  406. continue;
  407. if ((0 == padapter->registrypriv.ht_enable) &&
  408. (o->inc == 8))
  409. continue;
  410. if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
  411. ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
  412. continue;
  413. if (reg == NULL) {
  414. reg = &channel_list->reg_class[cla];
  415. cla++;
  416. reg->reg_class = o->op_class;
  417. reg->channels = 0;
  418. }
  419. reg->channel[reg->channels] = ch;
  420. reg->channels++;
  421. }
  422. }
  423. channel_list->reg_classes = cla;
  424. }
  425. static u8 init_channel_set(struct rtw_adapter *padapter, u8 cplan,
  426. struct rt_channel_info *c_set)
  427. {
  428. u8 i, ch_size = 0;
  429. u8 b5GBand = false, b2_4GBand = false;
  430. u8 Index2G = 0, Index5G = 0;
  431. memset(c_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
  432. if (cplan >= RT_CHANNEL_DOMAIN_MAX &&
  433. cplan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
  434. DBG_8723A("ChannelPlan ID %x error !!!!!\n", cplan);
  435. return ch_size;
  436. }
  437. if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
  438. b2_4GBand = true;
  439. if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
  440. Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
  441. else
  442. Index2G = RTW_ChannelPlanMap[cplan].Index2G;
  443. }
  444. if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
  445. b5GBand = true;
  446. if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == cplan)
  447. Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
  448. else
  449. Index5G = RTW_ChannelPlanMap[cplan].Index5G;
  450. }
  451. if (b2_4GBand) {
  452. for (i = 0; i < RTW_ChannelPlan2G[Index2G].Len; i++) {
  453. c_set[ch_size].ChannelNum =
  454. RTW_ChannelPlan2G[Index2G].Channel[i];
  455. if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == cplan) ||
  456. /* Channel 1~11 is active, and 12~14 is passive */
  457. RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == cplan) {
  458. if (c_set[ch_size].ChannelNum >= 1 &&
  459. c_set[ch_size].ChannelNum <= 11)
  460. c_set[ch_size].ScanType = SCAN_ACTIVE;
  461. else if (c_set[ch_size].ChannelNum >= 12 &&
  462. c_set[ch_size].ChannelNum <= 14)
  463. c_set[ch_size].ScanType = SCAN_PASSIVE;
  464. } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == cplan ||
  465. RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan ||
  466. RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
  467. /* channel 12~13, passive scan */
  468. if (c_set[ch_size].ChannelNum <= 11)
  469. c_set[ch_size].ScanType = SCAN_ACTIVE;
  470. else
  471. c_set[ch_size].ScanType = SCAN_PASSIVE;
  472. } else
  473. c_set[ch_size].ScanType = SCAN_ACTIVE;
  474. ch_size++;
  475. }
  476. }
  477. if (b5GBand) {
  478. for (i = 0; i < RTW_ChannelPlan5G[Index5G].Len; i++) {
  479. if (RTW_ChannelPlan5G[Index5G].Channel[i] <= 48 ||
  480. RTW_ChannelPlan5G[Index5G].Channel[i] >= 149) {
  481. c_set[ch_size].ChannelNum =
  482. RTW_ChannelPlan5G[Index5G].Channel[i];
  483. if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == cplan) {
  484. /* passive scan for all 5G channels */
  485. c_set[ch_size].ScanType =
  486. SCAN_PASSIVE;
  487. } else
  488. c_set[ch_size].ScanType =
  489. SCAN_ACTIVE;
  490. DBG_8723A("%s(): channel_set[%d].ChannelNum = "
  491. "%d\n", __func__, ch_size,
  492. c_set[ch_size].ChannelNum);
  493. ch_size++;
  494. }
  495. }
  496. }
  497. return ch_size;
  498. }
  499. int init_mlme_ext_priv23a(struct rtw_adapter *padapter)
  500. {
  501. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  502. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  503. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  504. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  505. pmlmeext->padapter = padapter;
  506. init_mlme_ext_priv23a_value(padapter);
  507. pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
  508. init_mlme_ext_timer23a(padapter);
  509. #ifdef CONFIG_8723AU_AP_MODE
  510. init_mlme_ap_info23a(padapter);
  511. #endif
  512. pmlmeext->max_chan_nums = init_channel_set(padapter,
  513. pmlmepriv->ChannelPlan,
  514. pmlmeext->channel_set);
  515. init_channel_list(padapter, pmlmeext->channel_set,
  516. pmlmeext->max_chan_nums, &pmlmeext->channel_list);
  517. pmlmeext->chan_scan_time = SURVEY_TO;
  518. pmlmeext->mlmeext_init = true;
  519. pmlmeext->active_keep_alive_check = true;
  520. return _SUCCESS;
  521. }
  522. void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
  523. {
  524. struct rtw_adapter *padapter = pmlmeext->padapter;
  525. if (!padapter)
  526. return;
  527. if (padapter->bDriverStopped == true) {
  528. del_timer_sync(&pmlmeext->survey_timer);
  529. del_timer_sync(&pmlmeext->link_timer);
  530. /* del_timer_sync(&pmlmeext->ADDBA_timer); */
  531. }
  532. }
  533. static void
  534. _mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
  535. struct recv_frame *precv_frame)
  536. {
  537. struct sk_buff *skb = precv_frame->pkt;
  538. struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
  539. if (ptable->func) {
  540. /* receive the frames that ra(a1) is my address
  541. or ra(a1) is bc address. */
  542. if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
  543. !is_broadcast_ether_addr(hdr->addr1))
  544. return;
  545. ptable->func(padapter, precv_frame);
  546. }
  547. }
  548. void mgt_dispatcher23a(struct rtw_adapter *padapter,
  549. struct recv_frame *precv_frame)
  550. {
  551. struct mlme_handler *ptable;
  552. #ifdef CONFIG_8723AU_AP_MODE
  553. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  554. #endif /* CONFIG_8723AU_AP_MODE */
  555. struct sk_buff *skb = precv_frame->pkt;
  556. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  557. struct sta_info *psta;
  558. u16 stype;
  559. int index;
  560. if (!ieee80211_is_mgmt(mgmt->frame_control))
  561. return;
  562. /* receive the frames that ra(a1) is my address or ra(a1) is
  563. bc address. */
  564. if (!ether_addr_equal(mgmt->da, myid(&padapter->eeprompriv)) &&
  565. !is_broadcast_ether_addr(mgmt->da))
  566. return;
  567. ptable = mlme_sta_tbl;
  568. stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
  569. index = stype >> 4;
  570. if (index > 13) {
  571. RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
  572. "Currently we do not support reserved sub-fr-type =%d\n",
  573. index);
  574. return;
  575. }
  576. ptable += index;
  577. psta = rtw_get_stainfo23a(&padapter->stapriv, mgmt->sa);
  578. if (psta) {
  579. if (ieee80211_has_retry(mgmt->frame_control)) {
  580. if (precv_frame->attrib.seq_num ==
  581. psta->RxMgmtFrameSeqNum) {
  582. /* drop the duplicate management frame */
  583. DBG_8723A("Drop duplicate management frame "
  584. "with seq_num = %d.\n",
  585. precv_frame->attrib.seq_num);
  586. return;
  587. }
  588. }
  589. psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
  590. }
  591. #ifdef CONFIG_8723AU_AP_MODE
  592. switch (stype) {
  593. case IEEE80211_STYPE_AUTH:
  594. if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
  595. ptable->func = &OnAuth23a;
  596. else
  597. ptable->func = &OnAuth23aClient23a;
  598. /* pass through */
  599. case IEEE80211_STYPE_ASSOC_REQ:
  600. case IEEE80211_STYPE_REASSOC_REQ:
  601. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  602. break;
  603. case IEEE80211_STYPE_PROBE_REQ:
  604. if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
  605. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  606. else
  607. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  608. break;
  609. case IEEE80211_STYPE_BEACON:
  610. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  611. break;
  612. case IEEE80211_STYPE_ACTION:
  613. /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
  614. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  615. break;
  616. default:
  617. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  618. break;
  619. }
  620. #else
  621. _mgt_dispatcher23a(padapter, ptable, precv_frame);
  622. #endif
  623. }
  624. /****************************************************************************
  625. Following are the callback functions for each subtype of the management frames
  626. *****************************************************************************/
  627. static int
  628. OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  629. {
  630. const u8 *ie;
  631. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  632. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  633. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  634. struct wlan_bssid_ex *cur = &pmlmeinfo->network;
  635. struct sk_buff *skb = precv_frame->pkt;
  636. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  637. int len = skb->len;
  638. if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
  639. return _SUCCESS;
  640. if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
  641. !check_fwstate(pmlmepriv,
  642. WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
  643. return _SUCCESS;
  644. if (unlikely(!ieee80211_is_probe_req(mgmt->frame_control))) {
  645. printk(KERN_WARNING "%s: Received non probe request frame\n",
  646. __func__);
  647. return _FAIL;
  648. }
  649. len -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
  650. ie = cfg80211_find_ie(WLAN_EID_SSID, mgmt->u.probe_req.variable, len);
  651. /* check (wildcard) SSID */
  652. if (!ie)
  653. goto out;
  654. if ((ie[1] && memcmp(ie + 2, cur->Ssid.ssid, cur->Ssid.ssid_len)) ||
  655. (ie[1] == 0 && pmlmeinfo->hidden_ssid_mode)) {
  656. return _SUCCESS;
  657. }
  658. if (check_fwstate(pmlmepriv, _FW_LINKED) &&
  659. pmlmepriv->cur_network.join_res)
  660. issue_probersp(padapter, mgmt->sa);
  661. out:
  662. return _SUCCESS;
  663. }
  664. static int
  665. OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  666. {
  667. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  668. if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
  669. report_survey_event23a(padapter, precv_frame);
  670. return _SUCCESS;
  671. }
  672. return _SUCCESS;
  673. }
  674. static int
  675. OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  676. {
  677. int cam_idx;
  678. struct sta_info *psta;
  679. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  680. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  681. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  682. struct sta_priv *pstapriv = &padapter->stapriv;
  683. struct sk_buff *skb = precv_frame->pkt;
  684. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  685. int pkt_len = skb->len;
  686. struct wlan_bssid_ex *pbss;
  687. int ret = _SUCCESS;
  688. u8 *p, *pie;
  689. int pie_len;
  690. u32 ielen = 0;
  691. pie = mgmt->u.beacon.variable;
  692. pie_len = pkt_len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
  693. p = rtw_get_ie23a(pie, WLAN_EID_EXT_SUPP_RATES, &ielen, pie_len);
  694. if (p && ielen > 0) {
  695. if (p[1 + ielen] == 0x2D && p[2 + ielen] != 0x2D) {
  696. /* Invalid value 0x2D is detected in Extended Supported
  697. * Rates (ESR) IE. Try to fix the IE length to avoid
  698. * failed Beacon parsing.
  699. */
  700. DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
  701. "Beacon of BSSID: %pM. Fix the length of "
  702. "ESR IE to avoid failed Beacon parsing.\n",
  703. mgmt->bssid);
  704. p[1] = ielen - 1;
  705. }
  706. }
  707. if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
  708. report_survey_event23a(padapter, precv_frame);
  709. return _SUCCESS;
  710. }
  711. if (!ether_addr_equal(mgmt->bssid,
  712. get_my_bssid23a(&pmlmeinfo->network)))
  713. goto out;
  714. if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
  715. /* we should update current network before auth,
  716. or some IE is wrong */
  717. pbss = collect_bss_info(padapter, precv_frame);
  718. if (pbss) {
  719. update_network23a(&pmlmepriv->cur_network.network, pbss,
  720. padapter, true);
  721. rtw_get_bcn_info23a(&pmlmepriv->cur_network);
  722. kfree(pbss);
  723. }
  724. /* check the vendor of the assoc AP */
  725. pmlmeinfo->assoc_AP_vendor =
  726. check_assoc_AP23a((u8 *)&mgmt->u.beacon, pkt_len -
  727. offsetof(struct ieee80211_mgmt, u));
  728. /* update TSF Value */
  729. rtw_update_TSF(pmlmeext, mgmt);
  730. /* start auth */
  731. start_clnt_auth(padapter);
  732. return _SUCCESS;
  733. }
  734. if (((pmlmeinfo->state & 0x03) == MSR_AP) &&
  735. (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
  736. psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
  737. if (psta) {
  738. ret = rtw_check_bcn_info23a(padapter, mgmt, pkt_len);
  739. if (ret != _SUCCESS) {
  740. DBG_8723A_LEVEL(_drv_always_, "ap has changed, "
  741. "disconnect now\n");
  742. receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
  743. return _SUCCESS;
  744. }
  745. /* update WMM, ERP in the beacon */
  746. /* todo: the timer is used instead of
  747. the number of the beacon received */
  748. if ((sta_rx_pkts(psta) & 0xf) == 0) {
  749. /* DBG_8723A("update_bcn_info\n"); */
  750. update_beacon23a_info(padapter, mgmt,
  751. pkt_len, psta);
  752. }
  753. }
  754. } else if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
  755. psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
  756. if (psta) {
  757. /* update WMM, ERP in the beacon */
  758. /* todo: the timer is used instead of the
  759. number of the beacon received */
  760. if ((sta_rx_pkts(psta) & 0xf) == 0) {
  761. /* DBG_8723A("update_bcn_info\n"); */
  762. update_beacon23a_info(padapter, mgmt,
  763. pkt_len, psta);
  764. }
  765. } else {
  766. /* allocate a new CAM entry for IBSS station */
  767. cam_idx = allocate_fw_sta_entry23a(padapter);
  768. if (cam_idx == NUM_STA)
  769. goto out;
  770. /* get supported rate */
  771. if (update_sta_support_rate23a(padapter, pie, pie_len,
  772. cam_idx) == _FAIL) {
  773. pmlmeinfo->FW_sta_info[cam_idx].status = 0;
  774. goto out;
  775. }
  776. /* update TSF Value */
  777. rtw_update_TSF(pmlmeext, mgmt);
  778. /* report sta add event */
  779. report_add_sta_event23a(padapter, mgmt->sa,
  780. cam_idx);
  781. }
  782. }
  783. out:
  784. return _SUCCESS;
  785. }
  786. #ifdef CONFIG_8723AU_AP_MODE
  787. static int
  788. OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  789. {
  790. static struct sta_info stat;
  791. struct sta_info *pstat = NULL;
  792. struct sta_priv *pstapriv = &padapter->stapriv;
  793. struct security_priv *psecuritypriv = &padapter->securitypriv;
  794. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  795. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  796. struct sk_buff *skb = precv_frame->pkt;
  797. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  798. u8 *pframe;
  799. const u8 *p;
  800. unsigned char *sa;
  801. u16 auth_mode, seq, algorithm;
  802. int status, len = skb->len;
  803. if ((pmlmeinfo->state & 0x03) != MSR_AP)
  804. return _FAIL;
  805. DBG_8723A("+OnAuth23a\n");
  806. sa = mgmt->sa;
  807. auth_mode = psecuritypriv->dot11AuthAlgrthm;
  808. pframe = mgmt->u.auth.variable;
  809. len = skb->len - offsetof(struct ieee80211_mgmt, u.auth.variable);
  810. seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
  811. algorithm = le16_to_cpu(mgmt->u.auth.auth_alg);
  812. DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
  813. if (auth_mode == 2 &&
  814. psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP40 &&
  815. psecuritypriv->dot11PrivacyAlgrthm != WLAN_CIPHER_SUITE_WEP104)
  816. auth_mode = 0;
  817. /* rx a shared-key auth but shared not enabled, or */
  818. /* rx a open-system auth but shared-key is enabled */
  819. if ((algorithm != WLAN_AUTH_OPEN && auth_mode == 0) ||
  820. (algorithm == WLAN_AUTH_OPEN && auth_mode == 1)) {
  821. DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
  822. "=%d] %02X%02X%02X%02X%02X%02X\n",
  823. algorithm, auth_mode,
  824. sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
  825. status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
  826. goto auth_fail;
  827. }
  828. if (rtw_access_ctrl23a(padapter, sa) == false) {
  829. status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
  830. goto auth_fail;
  831. }
  832. pstat = rtw_get_stainfo23a(pstapriv, sa);
  833. if (!pstat) {
  834. /* allocate a new one */
  835. DBG_8723A("going to alloc stainfo for sa =%pM\n", sa);
  836. pstat = rtw_alloc_stainfo23a(pstapriv, sa, GFP_ATOMIC);
  837. if (!pstat) {
  838. DBG_8723A(" Exceed the upper limit of supported "
  839. "clients...\n");
  840. status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
  841. goto auth_fail;
  842. }
  843. pstat->state = WIFI_FW_AUTH_NULL;
  844. pstat->auth_seq = 0;
  845. /* pstat->flags = 0; */
  846. /* pstat->capability = 0; */
  847. } else {
  848. spin_lock_bh(&pstapriv->asoc_list_lock);
  849. if (!list_empty(&pstat->asoc_list)) {
  850. list_del_init(&pstat->asoc_list);
  851. pstapriv->asoc_list_cnt--;
  852. if (pstat->expire_to > 0) {
  853. /* TODO: STA re_auth within expire_to */
  854. }
  855. }
  856. spin_unlock_bh(&pstapriv->asoc_list_lock);
  857. if (seq == 1) {
  858. /* TODO: STA re_auth and auth timeout */
  859. }
  860. }
  861. spin_lock_bh(&pstapriv->auth_list_lock);
  862. if (list_empty(&pstat->auth_list)) {
  863. list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
  864. pstapriv->auth_list_cnt++;
  865. }
  866. spin_unlock_bh(&pstapriv->auth_list_lock);
  867. if (pstat->auth_seq == 0)
  868. pstat->expire_to = pstapriv->auth_to;
  869. if ((pstat->auth_seq + 1) != seq) {
  870. DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
  871. "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
  872. status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
  873. goto auth_fail;
  874. }
  875. if (algorithm == WLAN_AUTH_OPEN && (auth_mode == 0 || auth_mode == 2)) {
  876. if (seq == 1) {
  877. pstat->state &= ~WIFI_FW_AUTH_NULL;
  878. pstat->state |= WIFI_FW_AUTH_SUCCESS;
  879. pstat->expire_to = pstapriv->assoc_to;
  880. pstat->authalg = algorithm;
  881. } else {
  882. DBG_8723A("(2)auth rejected because out of seq "
  883. "[rx_seq =%d, exp_seq =%d]!\n",
  884. seq, pstat->auth_seq+1);
  885. status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
  886. goto auth_fail;
  887. }
  888. } else { /* shared system or auto authentication */
  889. if (seq == 1) {
  890. /* prepare for the challenging txt... */
  891. pstat->state &= ~WIFI_FW_AUTH_NULL;
  892. pstat->state |= WIFI_FW_AUTH_STATE;
  893. pstat->authalg = algorithm;
  894. pstat->auth_seq = 2;
  895. } else if (seq == 3) {
  896. /* checking for challenging txt... */
  897. DBG_8723A("checking for challenging txt...\n");
  898. p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pframe, len);
  899. if (!p || p[1] <= 0) {
  900. DBG_8723A("auth rejected because challenge "
  901. "failure!(1)\n");
  902. status = WLAN_STATUS_CHALLENGE_FAIL;
  903. goto auth_fail;
  904. }
  905. if (!memcmp(p + 2, pstat->chg_txt, 128)) {
  906. pstat->state &= ~WIFI_FW_AUTH_STATE;
  907. pstat->state |= WIFI_FW_AUTH_SUCCESS;
  908. /* challenging txt is correct... */
  909. pstat->expire_to = pstapriv->assoc_to;
  910. } else {
  911. DBG_8723A("auth rejected because challenge "
  912. "failure!\n");
  913. status = WLAN_STATUS_CHALLENGE_FAIL;
  914. goto auth_fail;
  915. }
  916. } else {
  917. DBG_8723A("(3)auth rejected because out of seq "
  918. "[rx_seq =%d, exp_seq =%d]!\n",
  919. seq, pstat->auth_seq+1);
  920. status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
  921. goto auth_fail;
  922. }
  923. }
  924. /* Now, we are going to issue_auth... */
  925. pstat->auth_seq = seq + 1;
  926. issue_auth(padapter, pstat, WLAN_STATUS_SUCCESS);
  927. if (pstat->state & WIFI_FW_AUTH_SUCCESS)
  928. pstat->auth_seq = 0;
  929. return _SUCCESS;
  930. auth_fail:
  931. if (pstat)
  932. rtw_free_stainfo23a(padapter, pstat);
  933. pstat = &stat;
  934. memset((char *)pstat, '\0', sizeof(stat));
  935. pstat->auth_seq = 2;
  936. ether_addr_copy(pstat->hwaddr, sa);
  937. issue_auth(padapter, pstat, (unsigned short)status);
  938. return _FAIL;
  939. }
  940. #endif
  941. static int
  942. OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  943. {
  944. unsigned int seq, status, algthm;
  945. unsigned int go2asoc = 0;
  946. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  947. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  948. struct sk_buff *skb = precv_frame->pkt;
  949. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  950. const u8 *p;
  951. u8 *pie;
  952. int plen = skb->len;
  953. DBG_8723A("%s\n", __func__);
  954. /* check A1 matches or not */
  955. if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
  956. return _SUCCESS;
  957. if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
  958. return _SUCCESS;
  959. pie = mgmt->u.auth.variable;
  960. plen -= offsetof(struct ieee80211_mgmt, u.auth.variable);
  961. algthm = le16_to_cpu(mgmt->u.auth.auth_alg);
  962. seq = le16_to_cpu(mgmt->u.auth.auth_transaction);
  963. status = le16_to_cpu(mgmt->u.auth.status_code);
  964. if (status) {
  965. DBG_8723A("clnt auth fail, status: %d\n", status);
  966. /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
  967. if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
  968. if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
  969. pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
  970. else
  971. pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
  972. /* pmlmeinfo->reauth_count = 0; */
  973. }
  974. set_link_timer(pmlmeext, 1);
  975. goto authclnt_fail;
  976. }
  977. if (seq == 2) {
  978. if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
  979. /* legendary shared system */
  980. p = cfg80211_find_ie(WLAN_EID_CHALLENGE, pie, plen);
  981. if (!p) {
  982. /* DBG_8723A("marc: no challenge text?\n"); */
  983. goto authclnt_fail;
  984. }
  985. memcpy((void *)(pmlmeinfo->chg_txt), p + 2, p[1]);
  986. pmlmeinfo->auth_seq = 3;
  987. issue_auth(padapter, NULL, 0);
  988. set_link_timer(pmlmeext, REAUTH_TO);
  989. return _SUCCESS;
  990. } else {
  991. /* open system */
  992. go2asoc = 1;
  993. }
  994. } else if (seq == 4) {
  995. if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
  996. go2asoc = 1;
  997. else
  998. goto authclnt_fail;
  999. } else {
  1000. /* this is also illegal */
  1001. /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n",
  1002. seq); */
  1003. goto authclnt_fail;
  1004. }
  1005. if (go2asoc) {
  1006. DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
  1007. start_clnt_assoc(padapter);
  1008. return _SUCCESS;
  1009. }
  1010. authclnt_fail:
  1011. /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
  1012. return _FAIL;
  1013. }
  1014. #ifdef CONFIG_8723AU_AP_MODE
  1015. static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
  1016. {
  1017. unsigned int oui;
  1018. /* first 3 bytes in vendor specific information element are the IEEE
  1019. * OUI of the vendor. The following byte is used a vendor specific
  1020. * sub-type. */
  1021. if (elen < 4) {
  1022. DBG_8723A("short vendor specific information element "
  1023. "ignored (len =%i)\n", elen);
  1024. return -EINVAL;
  1025. }
  1026. oui = RTW_GET_BE24(pos);
  1027. switch (oui) {
  1028. case WLAN_OUI_MICROSOFT:
  1029. /* Microsoft/Wi-Fi information elements are further typed and
  1030. * subtyped */
  1031. switch (pos[3]) {
  1032. case WLAN_OUI_TYPE_MICROSOFT_WPA:
  1033. /* Microsoft OUI (00:50:F2) with OUI Type 1:
  1034. * real WPA information element */
  1035. break;
  1036. case WLAN_OUI_TYPE_MICROSOFT_WMM:
  1037. if (elen < 5) {
  1038. DBG_8723A("short WME information element "
  1039. "ignored (len =%i)\n", elen);
  1040. return -EINVAL;
  1041. }
  1042. switch (pos[4]) {
  1043. case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
  1044. case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
  1045. break;
  1046. case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
  1047. break;
  1048. default:
  1049. DBG_8723A("unknown WME information element "
  1050. "ignored (subtype =%d len =%i)\n",
  1051. pos[4], elen);
  1052. return -EINVAL;
  1053. }
  1054. break;
  1055. case WLAN_OUI_TYPE_MICROSOFT_WPS:
  1056. /* Wi-Fi Protected Setup (WPS) IE */
  1057. break;
  1058. default:
  1059. DBG_8723A("Unknown Microsoft information element "
  1060. "ignored (type =%d len =%i)\n",
  1061. pos[3], elen);
  1062. return -EINVAL;
  1063. }
  1064. break;
  1065. case OUI_BROADCOM:
  1066. switch (pos[3]) {
  1067. case VENDOR_HT_CAPAB_OUI_TYPE:
  1068. break;
  1069. default:
  1070. DBG_8723A("Unknown Broadcom information element "
  1071. "ignored (type =%d len =%i)\n", pos[3], elen);
  1072. return -EINVAL;
  1073. }
  1074. break;
  1075. default:
  1076. DBG_8723A("unknown vendor specific information element "
  1077. "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
  1078. pos[0], pos[1], pos[2], elen);
  1079. return -EINVAL;
  1080. }
  1081. return 0;
  1082. }
  1083. static int rtw_validate_frame_ies(const u8 *start, uint len)
  1084. {
  1085. const u8 *pos = start;
  1086. int left = len;
  1087. int unknown = 0;
  1088. while (left >= 2) {
  1089. u8 id, elen;
  1090. id = *pos++;
  1091. elen = *pos++;
  1092. left -= 2;
  1093. if (elen > left) {
  1094. DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
  1095. "left =%i)\n", __func__, id, elen, left);
  1096. return -EINVAL;
  1097. }
  1098. switch (id) {
  1099. case WLAN_EID_SSID:
  1100. case WLAN_EID_SUPP_RATES:
  1101. case WLAN_EID_FH_PARAMS:
  1102. case WLAN_EID_DS_PARAMS:
  1103. case WLAN_EID_CF_PARAMS:
  1104. case WLAN_EID_TIM:
  1105. case WLAN_EID_IBSS_PARAMS:
  1106. case WLAN_EID_CHALLENGE:
  1107. case WLAN_EID_ERP_INFO:
  1108. case WLAN_EID_EXT_SUPP_RATES:
  1109. break;
  1110. case WLAN_EID_VENDOR_SPECIFIC:
  1111. if (rtw_validate_vendor_specific_ies(pos, elen))
  1112. unknown++;
  1113. break;
  1114. case WLAN_EID_RSN:
  1115. case WLAN_EID_PWR_CAPABILITY:
  1116. case WLAN_EID_SUPPORTED_CHANNELS:
  1117. case WLAN_EID_MOBILITY_DOMAIN:
  1118. case WLAN_EID_FAST_BSS_TRANSITION:
  1119. case WLAN_EID_TIMEOUT_INTERVAL:
  1120. case WLAN_EID_HT_CAPABILITY:
  1121. case WLAN_EID_HT_OPERATION:
  1122. default:
  1123. unknown++;
  1124. DBG_8723A("%s IEEE 802.11 ignored unknown element "
  1125. "(id =%d elen =%d)\n", __func__, id, elen);
  1126. break;
  1127. }
  1128. left -= elen;
  1129. pos += elen;
  1130. }
  1131. if (left)
  1132. return -EINVAL;
  1133. return 0;
  1134. }
  1135. #endif
  1136. static int
  1137. OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1138. {
  1139. #ifdef CONFIG_8723AU_AP_MODE
  1140. u16 capab_info, listen_interval;
  1141. struct sta_info *pstat;
  1142. unsigned char reassoc;
  1143. int i, wpa_ie_len, left;
  1144. unsigned char supportRate[16];
  1145. int supportRateNum;
  1146. unsigned short status = WLAN_STATUS_SUCCESS;
  1147. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1148. struct security_priv *psecuritypriv = &padapter->securitypriv;
  1149. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1150. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1151. struct wlan_bssid_ex *cur = &pmlmeinfo->network;
  1152. struct sta_priv *pstapriv = &padapter->stapriv;
  1153. struct sk_buff *skb = precv_frame->pkt;
  1154. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  1155. const u8 *pos, *p, *wpa_ie, *wps_ie;
  1156. u8 *pframe = skb->data;
  1157. uint pkt_len = skb->len;
  1158. int r;
  1159. if ((pmlmeinfo->state & 0x03) != MSR_AP)
  1160. return _FAIL;
  1161. left = pkt_len - sizeof(struct ieee80211_hdr_3addr);
  1162. if (ieee80211_is_assoc_req(mgmt->frame_control)) {
  1163. reassoc = 0;
  1164. pos = mgmt->u.assoc_req.variable;
  1165. left -= offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
  1166. } else { /* WIFI_REASSOCREQ */
  1167. reassoc = 1;
  1168. pos = mgmt->u.reassoc_req.variable;
  1169. left -= offsetof(struct ieee80211_mgmt, u.reassoc_req.variable);
  1170. }
  1171. if (left < 0) {
  1172. DBG_8723A("handle_assoc(reassoc =%d) - too short payload "
  1173. "(len =%lu)\n", reassoc, (unsigned long)pkt_len);
  1174. return _FAIL;
  1175. }
  1176. pstat = rtw_get_stainfo23a(pstapriv, mgmt->sa);
  1177. if (!pstat) {
  1178. status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
  1179. goto asoc_class2_error;
  1180. }
  1181. /* These two are located at the same offsets whether it's an
  1182. * assoc_req or a reassoc_req */
  1183. capab_info = get_unaligned_le16(&mgmt->u.assoc_req.capab_info);
  1184. listen_interval =
  1185. get_unaligned_le16(&mgmt->u.assoc_req.listen_interval);
  1186. DBG_8723A("%s\n", __func__);
  1187. /* check if this stat has been successfully authenticated/assocated */
  1188. if (!(pstat->state & WIFI_FW_AUTH_SUCCESS)) {
  1189. if (!(pstat->state & WIFI_FW_ASSOC_SUCCESS)) {
  1190. status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
  1191. goto asoc_class2_error;
  1192. } else {
  1193. pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
  1194. pstat->state |= WIFI_FW_ASSOC_STATE;
  1195. }
  1196. } else {
  1197. pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
  1198. pstat->state |= WIFI_FW_ASSOC_STATE;
  1199. }
  1200. pstat->capability = capab_info;
  1201. /* now parse all ieee802_11 ie to point to elems */
  1202. if (rtw_validate_frame_ies(pos, left)) {
  1203. DBG_8723A("STA %pM sent invalid association request\n",
  1204. pstat->hwaddr);
  1205. status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  1206. goto OnAssocReq23aFail;
  1207. }
  1208. /* now we should check all the fields... */
  1209. /* checking SSID */
  1210. p = cfg80211_find_ie(WLAN_EID_SSID, pos, left);
  1211. if (!p || p[1] == 0) {
  1212. /* broadcast ssid, however it is not allowed in assocreq */
  1213. DBG_8723A("STA %pM sent invalid association request lacking an SSID\n",
  1214. pstat->hwaddr);
  1215. status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  1216. goto OnAssocReq23aFail;
  1217. } else {
  1218. /* check if ssid match */
  1219. if (memcmp(p + 2, cur->Ssid.ssid, cur->Ssid.ssid_len))
  1220. status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  1221. if (p[1] != cur->Ssid.ssid_len)
  1222. status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  1223. }
  1224. if (status != WLAN_STATUS_SUCCESS)
  1225. goto OnAssocReq23aFail;
  1226. /* check if the supported rate is ok */
  1227. p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, pos, left);
  1228. if (!p) {
  1229. DBG_8723A("Rx a sta assoc-req which supported rate is "
  1230. "empty!\n");
  1231. /* use our own rate set as statoin used */
  1232. /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
  1233. /* supportRateNum = AP_BSSRATE_LEN; */
  1234. status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  1235. goto OnAssocReq23aFail;
  1236. } else {
  1237. memcpy(supportRate, p + 2, p[1]);
  1238. supportRateNum = p[1];
  1239. p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, pos, left);
  1240. if (p) {
  1241. if (supportRateNum <= sizeof(supportRate)) {
  1242. memcpy(supportRate+supportRateNum, p + 2, p[1]);
  1243. supportRateNum += p[1];
  1244. }
  1245. }
  1246. }
  1247. /* todo: mask supportRate between AP & STA -> move to update raid */
  1248. /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
  1249. /* update station supportRate */
  1250. pstat->bssratelen = supportRateNum;
  1251. memcpy(pstat->bssrateset, supportRate, supportRateNum);
  1252. Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
  1253. /* check RSN/WPA/WPS */
  1254. pstat->dot8021xalg = 0;
  1255. pstat->wpa_psk = 0;
  1256. pstat->wpa_group_cipher = 0;
  1257. pstat->wpa2_group_cipher = 0;
  1258. pstat->wpa_pairwise_cipher = 0;
  1259. pstat->wpa2_pairwise_cipher = 0;
  1260. memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
  1261. wpa_ie = cfg80211_find_ie(WLAN_EID_RSN, pos, left);
  1262. if (!wpa_ie)
  1263. wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
  1264. WLAN_OUI_TYPE_MICROSOFT_WPA,
  1265. pos, left);
  1266. if (wpa_ie) {
  1267. int group_cipher = 0, pairwise_cipher = 0;
  1268. wpa_ie_len = wpa_ie[1];
  1269. if (psecuritypriv->wpa_psk & BIT(1)) {
  1270. r = rtw_parse_wpa2_ie23a(wpa_ie, wpa_ie_len + 2,
  1271. &group_cipher,
  1272. &pairwise_cipher, NULL);
  1273. if (r == _SUCCESS) {
  1274. pstat->dot8021xalg = 1;/* psk, todo:802.1x */
  1275. pstat->wpa_psk |= BIT(1);
  1276. pstat->wpa2_group_cipher = group_cipher &
  1277. psecuritypriv->wpa2_group_cipher;
  1278. pstat->wpa2_pairwise_cipher = pairwise_cipher &
  1279. psecuritypriv->wpa2_pairwise_cipher;
  1280. } else
  1281. status = WLAN_STATUS_INVALID_IE;
  1282. } else if (psecuritypriv->wpa_psk & BIT(0)) {
  1283. r = rtw_parse_wpa_ie23a(wpa_ie, wpa_ie_len + 2,
  1284. &group_cipher, &pairwise_cipher,
  1285. NULL);
  1286. if (r == _SUCCESS) {
  1287. pstat->dot8021xalg = 1;/* psk, todo:802.1x */
  1288. pstat->wpa_psk |= BIT(0);
  1289. pstat->wpa_group_cipher = group_cipher &
  1290. psecuritypriv->wpa_group_cipher;
  1291. pstat->wpa_pairwise_cipher = pairwise_cipher &
  1292. psecuritypriv->wpa_pairwise_cipher;
  1293. } else
  1294. status = WLAN_STATUS_INVALID_IE;
  1295. } else {
  1296. wpa_ie = NULL;
  1297. wpa_ie_len = 0;
  1298. }
  1299. if (wpa_ie && status == WLAN_STATUS_SUCCESS) {
  1300. if (!pstat->wpa_group_cipher)
  1301. status = WLAN_STATUS_INVALID_GROUP_CIPHER;
  1302. if (!pstat->wpa_pairwise_cipher)
  1303. status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
  1304. }
  1305. }
  1306. if (status != WLAN_STATUS_SUCCESS)
  1307. goto OnAssocReq23aFail;
  1308. pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
  1309. wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
  1310. WLAN_OUI_TYPE_MICROSOFT_WPS,
  1311. pos, left);
  1312. if (!wpa_ie) {
  1313. if (wps_ie) {
  1314. DBG_8723A("STA included WPS IE in (Re)Association "
  1315. "Request - assume WPS is used\n");
  1316. pstat->flags |= WLAN_STA_WPS;
  1317. } else {
  1318. DBG_8723A("STA did not include WPA/RSN IE in (Re)"
  1319. "Association Request - possible WPS use\n");
  1320. pstat->flags |= WLAN_STA_MAYBE_WPS;
  1321. }
  1322. } else {
  1323. int copy_len;
  1324. if (psecuritypriv->wpa_psk == 0) {
  1325. DBG_8723A("STA %pM: WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
  1326. pstat->hwaddr);
  1327. status = WLAN_STATUS_INVALID_IE;
  1328. goto OnAssocReq23aFail;
  1329. }
  1330. if (wps_ie) {
  1331. DBG_8723A("STA included WPS IE in (Re)Association "
  1332. "Request - WPS is used\n");
  1333. pstat->flags |= WLAN_STA_WPS;
  1334. copy_len = 0;
  1335. } else {
  1336. copy_len = ((wpa_ie_len + 2) > sizeof(pstat->wpa_ie)) ?
  1337. sizeof(pstat->wpa_ie) : (wpa_ie_len + 2);
  1338. }
  1339. if (copy_len > 0)
  1340. memcpy(pstat->wpa_ie, wpa_ie - 2, copy_len);
  1341. }
  1342. /* check if there is WMM IE & support WWM-PS */
  1343. pstat->flags &= ~WLAN_STA_WME;
  1344. pstat->qos_option = 0;
  1345. pstat->qos_info = 0;
  1346. pstat->has_legacy_ac = true;
  1347. pstat->uapsd_vo = 0;
  1348. pstat->uapsd_vi = 0;
  1349. pstat->uapsd_be = 0;
  1350. pstat->uapsd_bk = 0;
  1351. if (pmlmepriv->qos_option) {
  1352. const u8 *end = pos + left;
  1353. p = pos;
  1354. for (;;) {
  1355. left = end - p;
  1356. p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
  1357. WLAN_OUI_TYPE_MICROSOFT_WMM,
  1358. p, left);
  1359. if (p) {
  1360. pstat->flags |= WLAN_STA_WME;
  1361. pstat->qos_option = 1;
  1362. pstat->qos_info = *(p + 8);
  1363. pstat->max_sp_len =
  1364. (pstat->qos_info >> 5) & 0x3;
  1365. if ((pstat->qos_info & 0xf) != 0xf)
  1366. pstat->has_legacy_ac = true;
  1367. else
  1368. pstat->has_legacy_ac = false;
  1369. if (pstat->qos_info & 0xf) {
  1370. if (pstat->qos_info & BIT(0))
  1371. pstat->uapsd_vo = BIT(0)|BIT(1);
  1372. else
  1373. pstat->uapsd_vo = 0;
  1374. if (pstat->qos_info & BIT(1))
  1375. pstat->uapsd_vi = BIT(0)|BIT(1);
  1376. else
  1377. pstat->uapsd_vi = 0;
  1378. if (pstat->qos_info & BIT(2))
  1379. pstat->uapsd_bk = BIT(0)|BIT(1);
  1380. else
  1381. pstat->uapsd_bk = 0;
  1382. if (pstat->qos_info & BIT(3))
  1383. pstat->uapsd_be = BIT(0)|BIT(1);
  1384. else
  1385. pstat->uapsd_be = 0;
  1386. break;
  1387. }
  1388. } else {
  1389. break;
  1390. }
  1391. p = p + p[1] + 2;
  1392. }
  1393. }
  1394. /* save HT capabilities in the sta object */
  1395. memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
  1396. p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pos, left);
  1397. if (p && p[1] >= sizeof(struct ieee80211_ht_cap)) {
  1398. pstat->flags |= WLAN_STA_HT;
  1399. pstat->flags |= WLAN_STA_WME;
  1400. memcpy(&pstat->htpriv.ht_cap, p + 2,
  1401. sizeof(struct ieee80211_ht_cap));
  1402. } else
  1403. pstat->flags &= ~WLAN_STA_HT;
  1404. if (!pmlmepriv->htpriv.ht_option && pstat->flags & WLAN_STA_HT){
  1405. status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  1406. goto OnAssocReq23aFail;
  1407. }
  1408. if (pstat->flags & WLAN_STA_HT &&
  1409. (pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP ||
  1410. pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
  1411. DBG_8723A("HT: %pM tried to use TKIP with HT association\n",
  1412. pstat->hwaddr);
  1413. /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
  1414. /* goto OnAssocReq23aFail; */
  1415. }
  1416. pstat->flags |= WLAN_STA_NONERP;
  1417. for (i = 0; i < pstat->bssratelen; i++) {
  1418. if ((pstat->bssrateset[i] & 0x7f) > 22) {
  1419. pstat->flags &= ~WLAN_STA_NONERP;
  1420. break;
  1421. }
  1422. }
  1423. if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
  1424. pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
  1425. else
  1426. pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
  1427. if (status != WLAN_STATUS_SUCCESS)
  1428. goto OnAssocReq23aFail;
  1429. /* TODO: identify_proprietary_vendor_ie(); */
  1430. /* Realtek proprietary IE */
  1431. /* identify if this is Broadcom sta */
  1432. /* identify if this is ralink sta */
  1433. /* Customer proprietary IE */
  1434. /* get a unique AID */
  1435. if (pstat->aid > 0) {
  1436. DBG_8723A(" old AID %d\n", pstat->aid);
  1437. } else {
  1438. for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
  1439. if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
  1440. break;
  1441. if (pstat->aid > NUM_STA)
  1442. pstat->aid = NUM_STA;
  1443. if (pstat->aid > pstapriv->max_num_sta) {
  1444. pstat->aid = 0;
  1445. DBG_8723A(" no room for more AIDs\n");
  1446. status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
  1447. goto OnAssocReq23aFail;
  1448. } else {
  1449. pstapriv->sta_aid[pstat->aid - 1] = pstat;
  1450. DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
  1451. }
  1452. }
  1453. pstat->state &= ~WIFI_FW_ASSOC_STATE;
  1454. pstat->state |= WIFI_FW_ASSOC_SUCCESS;
  1455. spin_lock_bh(&pstapriv->auth_list_lock);
  1456. if (!list_empty(&pstat->auth_list)) {
  1457. list_del_init(&pstat->auth_list);
  1458. pstapriv->auth_list_cnt--;
  1459. }
  1460. spin_unlock_bh(&pstapriv->auth_list_lock);
  1461. spin_lock_bh(&pstapriv->asoc_list_lock);
  1462. if (list_empty(&pstat->asoc_list)) {
  1463. pstat->expire_to = pstapriv->expire_to;
  1464. list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
  1465. pstapriv->asoc_list_cnt++;
  1466. }
  1467. spin_unlock_bh(&pstapriv->asoc_list_lock);
  1468. /* now the station is qualified to join our BSS... */
  1469. if (pstat->state & WIFI_FW_ASSOC_SUCCESS &&
  1470. status == WLAN_STATUS_SUCCESS) {
  1471. /* 1 bss_cap_update & sta_info_update23a */
  1472. bss_cap_update_on_sta_join23a(padapter, pstat);
  1473. sta_info_update23a(padapter, pstat);
  1474. /* issue assoc rsp before notify station join event. */
  1475. if (ieee80211_is_assoc_req(mgmt->frame_control))
  1476. issue_assocrsp(padapter, status, pstat,
  1477. IEEE80211_STYPE_ASSOC_RESP);
  1478. else
  1479. issue_assocrsp(padapter, status, pstat,
  1480. IEEE80211_STYPE_REASSOC_RESP);
  1481. /* 2 - report to upper layer */
  1482. DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
  1483. rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
  1484. /* 3-(1) report sta add event */
  1485. report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
  1486. }
  1487. return _SUCCESS;
  1488. asoc_class2_error:
  1489. issue_deauth23a(padapter, mgmt->sa, status);
  1490. return _FAIL;
  1491. OnAssocReq23aFail:
  1492. pstat->aid = 0;
  1493. if (ieee80211_is_assoc_req(mgmt->frame_control))
  1494. issue_assocrsp(padapter, status, pstat,
  1495. IEEE80211_STYPE_ASSOC_RESP);
  1496. else
  1497. issue_assocrsp(padapter, status, pstat,
  1498. IEEE80211_STYPE_REASSOC_RESP);
  1499. #endif /* CONFIG_8723AU_AP_MODE */
  1500. return _FAIL;
  1501. }
  1502. static int
  1503. OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1504. {
  1505. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1506. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1507. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1508. struct sk_buff *skb = precv_frame->pkt;
  1509. struct ieee80211_mgmt *pmgmt = (struct ieee80211_mgmt *) skb->data;
  1510. int res;
  1511. unsigned short status;
  1512. const u8 *p, *pie;
  1513. u8 *pframe = skb->data;
  1514. int pkt_len = skb->len;
  1515. int pielen;
  1516. DBG_8723A("%s\n", __func__);
  1517. /* check A1 matches or not */
  1518. if (!ether_addr_equal(myid(&padapter->eeprompriv), pmgmt->da))
  1519. return _SUCCESS;
  1520. if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
  1521. return _SUCCESS;
  1522. if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
  1523. return _SUCCESS;
  1524. del_timer_sync(&pmlmeext->link_timer);
  1525. /* status */
  1526. status = le16_to_cpu(pmgmt->u.assoc_resp.status_code);
  1527. if (status > 0) {
  1528. DBG_8723A("assoc reject, status code: %d\n", status);
  1529. pmlmeinfo->state = MSR_NOLINK;
  1530. res = -4;
  1531. goto report_assoc_result;
  1532. }
  1533. /* get capabilities */
  1534. pmlmeinfo->capability = le16_to_cpu(pmgmt->u.assoc_resp.capab_info);
  1535. /* set slot time */
  1536. pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
  1537. /* AID */
  1538. res = pmlmeinfo->aid = le16_to_cpu(pmgmt->u.assoc_resp.aid) & 0x3fff;
  1539. pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  1540. pielen = pkt_len -
  1541. offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  1542. p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
  1543. pmgmt->u.assoc_resp.variable, pielen);
  1544. if (p && p[1])
  1545. HT_caps_handler23a(padapter, p);
  1546. p = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
  1547. pmgmt->u.assoc_resp.variable, pielen);
  1548. if (p && p[1])
  1549. HT_info_handler23a(padapter, p);
  1550. p = cfg80211_find_ie(WLAN_EID_ERP_INFO,
  1551. pmgmt->u.assoc_resp.variable, pielen);
  1552. if (p && p[1])
  1553. ERP_IE_handler23a(padapter, p);
  1554. pie = pframe + offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  1555. while (true) {
  1556. p = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
  1557. WLAN_OUI_TYPE_MICROSOFT_WMM,
  1558. pie, pframe + pkt_len - pie);
  1559. if (!p)
  1560. break;
  1561. pie = p + p[1] + 2;
  1562. /* if this IE is too short, try the next */
  1563. if (p[1] <= 4)
  1564. continue;
  1565. /* if this IE is WMM params, we found what we wanted */
  1566. if (p[6] == 1)
  1567. break;
  1568. }
  1569. if (p && p[1])
  1570. WMM_param_handler23a(padapter, p);
  1571. pmlmeinfo->state &= ~WIFI_FW_ASSOC_STATE;
  1572. pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
  1573. /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
  1574. UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
  1575. report_assoc_result:
  1576. pmlmepriv->assoc_rsp_len = 0;
  1577. if (res > 0) {
  1578. kfree(pmlmepriv->assoc_rsp);
  1579. pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
  1580. if (pmlmepriv->assoc_rsp) {
  1581. memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
  1582. pmlmepriv->assoc_rsp_len = pkt_len;
  1583. }
  1584. } else
  1585. kfree(pmlmepriv->assoc_rsp);
  1586. report_join_res23a(padapter, res);
  1587. return _SUCCESS;
  1588. }
  1589. static int
  1590. OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1591. {
  1592. unsigned short reason;
  1593. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1594. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1595. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1596. struct sk_buff *skb = precv_frame->pkt;
  1597. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  1598. if (!ether_addr_equal(mgmt->bssid,
  1599. get_my_bssid23a(&pmlmeinfo->network)))
  1600. return _SUCCESS;
  1601. reason = le16_to_cpu(mgmt->u.deauth.reason_code);
  1602. DBG_8723A("%s Reason code(%d)\n", __func__, reason);
  1603. #ifdef CONFIG_8723AU_AP_MODE
  1604. if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
  1605. struct sta_info *psta;
  1606. struct sta_priv *pstapriv = &padapter->stapriv;
  1607. DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
  1608. "sta:%pM\n", reason, mgmt->sa);
  1609. psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
  1610. if (psta) {
  1611. u8 updated = 0;
  1612. spin_lock_bh(&pstapriv->asoc_list_lock);
  1613. if (!list_empty(&psta->asoc_list)) {
  1614. list_del_init(&psta->asoc_list);
  1615. pstapriv->asoc_list_cnt--;
  1616. updated = ap_free_sta23a(padapter, psta,
  1617. false, reason);
  1618. }
  1619. spin_unlock_bh(&pstapriv->asoc_list_lock);
  1620. associated_clients_update23a(padapter, updated);
  1621. }
  1622. return _SUCCESS;
  1623. } else
  1624. #endif
  1625. {
  1626. DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
  1627. "sta:%pM\n", reason, mgmt->bssid);
  1628. receive_disconnect23a(padapter, mgmt->bssid, reason);
  1629. }
  1630. pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
  1631. return _SUCCESS;
  1632. }
  1633. static int
  1634. OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1635. {
  1636. unsigned short reason;
  1637. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1638. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1639. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1640. struct sk_buff *skb = precv_frame->pkt;
  1641. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  1642. if (!ether_addr_equal(mgmt->bssid,
  1643. get_my_bssid23a(&pmlmeinfo->network)))
  1644. return _SUCCESS;
  1645. reason = le16_to_cpu(mgmt->u.disassoc.reason_code);
  1646. DBG_8723A("%s Reason code(%d)\n", __func__, reason);
  1647. #ifdef CONFIG_8723AU_AP_MODE
  1648. if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
  1649. struct sta_info *psta;
  1650. struct sta_priv *pstapriv = &padapter->stapriv;
  1651. DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
  1652. " sta:%pM\n", reason, mgmt->sa);
  1653. psta = rtw_get_stainfo23a(pstapriv, mgmt->sa);
  1654. if (psta) {
  1655. u8 updated = 0;
  1656. spin_lock_bh(&pstapriv->asoc_list_lock);
  1657. if (!list_empty(&psta->asoc_list)) {
  1658. list_del_init(&psta->asoc_list);
  1659. pstapriv->asoc_list_cnt--;
  1660. updated = ap_free_sta23a(padapter, psta,
  1661. false, reason);
  1662. }
  1663. spin_unlock_bh(&pstapriv->asoc_list_lock);
  1664. associated_clients_update23a(padapter, updated);
  1665. }
  1666. return _SUCCESS;
  1667. } else
  1668. #endif
  1669. {
  1670. DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
  1671. "code(%d) sta:%pM\n", reason, mgmt->bssid);
  1672. receive_disconnect23a(padapter, mgmt->bssid, reason);
  1673. }
  1674. pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
  1675. return _SUCCESS;
  1676. }
  1677. static int
  1678. OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1679. {
  1680. DBG_8723A("%s\n", __func__);
  1681. return _SUCCESS;
  1682. }
  1683. static int
  1684. on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1685. {
  1686. return _FAIL;
  1687. }
  1688. static int
  1689. OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1690. {
  1691. return _SUCCESS;
  1692. }
  1693. static int
  1694. OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1695. {
  1696. return _SUCCESS;
  1697. }
  1698. static int OnAction23a_back23a(struct rtw_adapter *padapter,
  1699. struct recv_frame *precv_frame)
  1700. {
  1701. u8 *addr;
  1702. struct sta_info *psta = NULL;
  1703. struct recv_reorder_ctrl *preorder_ctrl;
  1704. unsigned char category, action;
  1705. unsigned short tid, status, capab, params, reason_code = 0;
  1706. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1707. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1708. struct sk_buff *skb = precv_frame->pkt;
  1709. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  1710. struct sta_priv *pstapriv = &padapter->stapriv;
  1711. /* check RA matches or not */
  1712. if (!ether_addr_equal(myid(&padapter->eeprompriv), mgmt->da))
  1713. return _SUCCESS;
  1714. DBG_8723A("%s\n", __func__);
  1715. if ((pmlmeinfo->state&0x03) != MSR_AP)
  1716. if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
  1717. return _SUCCESS;
  1718. addr = mgmt->sa;
  1719. psta = rtw_get_stainfo23a(pstapriv, addr);
  1720. if (!psta)
  1721. return _SUCCESS;
  1722. category = mgmt->u.action.category;
  1723. if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
  1724. if (!pmlmeinfo->HT_enable)
  1725. return _SUCCESS;
  1726. /* action_code is located in the same place for all
  1727. action events, so pick any */
  1728. action = mgmt->u.action.u.wme_action.action_code;
  1729. DBG_8723A("%s, action =%d\n", __func__, action);
  1730. switch (action) {
  1731. case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
  1732. memcpy(&pmlmeinfo->ADDBA_req,
  1733. &mgmt->u.action.u.addba_req.dialog_token,
  1734. sizeof(struct ADDBA_request));
  1735. process_addba_req23a(padapter,
  1736. (u8 *)&pmlmeinfo->ADDBA_req, addr);
  1737. if (pmlmeinfo->bAcceptAddbaReq == true)
  1738. issue_action_BA23a(padapter, addr,
  1739. WLAN_ACTION_ADDBA_RESP, 0);
  1740. else {
  1741. /* reject ADDBA Req */
  1742. issue_action_BA23a(padapter, addr,
  1743. WLAN_ACTION_ADDBA_RESP, 37);
  1744. }
  1745. break;
  1746. case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
  1747. status = get_unaligned_le16(
  1748. &mgmt->u.action.u.addba_resp.status);
  1749. capab = get_unaligned_le16(
  1750. &mgmt->u.action.u.addba_resp.capab);
  1751. tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
  1752. if (status == 0) { /* successful */
  1753. DBG_8723A("agg_enable for TID =%d\n", tid);
  1754. psta->htpriv.agg_enable_bitmap |= BIT(tid);
  1755. psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
  1756. } else
  1757. psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
  1758. break;
  1759. case WLAN_ACTION_DELBA: /* DELBA */
  1760. params = get_unaligned_le16(
  1761. &mgmt->u.action.u.delba.params);
  1762. tid = params >> 12;
  1763. if (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) {
  1764. preorder_ctrl = &psta->recvreorder_ctrl[tid];
  1765. preorder_ctrl->enable = false;
  1766. preorder_ctrl->indicate_seq = 0xffff;
  1767. } else {
  1768. psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
  1769. psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
  1770. }
  1771. reason_code = get_unaligned_le16(
  1772. &mgmt->u.action.u.delba.reason_code);
  1773. /* todo: how to notify the host while receiving
  1774. DELETE BA */
  1775. break;
  1776. default:
  1777. break;
  1778. }
  1779. }
  1780. return _SUCCESS;
  1781. }
  1782. static int on_action_public23a(struct rtw_adapter *padapter,
  1783. struct recv_frame *precv_frame)
  1784. {
  1785. struct sk_buff *skb = precv_frame->pkt;
  1786. struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
  1787. u8 *pframe = skb->data;
  1788. int freq, channel;
  1789. /* check RA matches or not */
  1790. if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
  1791. return _FAIL;
  1792. channel = rtw_get_oper_ch23a(padapter);
  1793. if (channel <= RTW_CH_MAX_2G_CHANNEL)
  1794. freq = ieee80211_channel_to_frequency(channel,
  1795. NL80211_BAND_2GHZ);
  1796. else
  1797. freq = ieee80211_channel_to_frequency(channel,
  1798. NL80211_BAND_5GHZ);
  1799. if (cfg80211_rx_mgmt(padapter->rtw_wdev, freq, 0, pframe,
  1800. skb->len, 0))
  1801. return _SUCCESS;
  1802. return _FAIL;
  1803. }
  1804. static int
  1805. OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1806. {
  1807. return _SUCCESS;
  1808. }
  1809. static int
  1810. OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1811. {
  1812. return _SUCCESS;
  1813. }
  1814. static int
  1815. OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1816. {
  1817. return _SUCCESS;
  1818. }
  1819. static int
  1820. OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
  1821. {
  1822. int i;
  1823. u8 category;
  1824. struct action_handler *ptable;
  1825. struct sk_buff *skb = precv_frame->pkt;
  1826. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  1827. category = mgmt->u.action.category;
  1828. for (i = 0; i < ARRAY_SIZE(OnAction23a_tbl); i++) {
  1829. ptable = &OnAction23a_tbl[i];
  1830. if (category == ptable->num)
  1831. ptable->func(padapter, precv_frame);
  1832. }
  1833. return _SUCCESS;
  1834. }
  1835. static int DoReserved23a(struct rtw_adapter *padapter,
  1836. struct recv_frame *precv_frame)
  1837. {
  1838. return _SUCCESS;
  1839. }
  1840. struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
  1841. {
  1842. struct xmit_frame *pmgntframe;
  1843. struct xmit_buf *pxmitbuf;
  1844. pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
  1845. if (!pmgntframe) {
  1846. DBG_8723A("%s(%s): alloc xmitframe fail\n", __func__,
  1847. pxmitpriv->adapter->pnetdev->name);
  1848. goto exit;
  1849. }
  1850. pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
  1851. if (!pxmitbuf) {
  1852. DBG_8723A("%s(%s): alloc xmitbuf fail\n", __func__,
  1853. pxmitpriv->adapter->pnetdev->name);
  1854. rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
  1855. pmgntframe = NULL;
  1856. goto exit;
  1857. }
  1858. pmgntframe->frame_tag = MGNT_FRAMETAG;
  1859. pmgntframe->pxmitbuf = pxmitbuf;
  1860. pmgntframe->buf_addr = pxmitbuf->pbuf;
  1861. pxmitbuf->priv_data = pmgntframe;
  1862. exit:
  1863. return pmgntframe;
  1864. }
  1865. /****************************************************************************
  1866. Following are some TX functions for WiFi MLME
  1867. *****************************************************************************/
  1868. void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
  1869. {
  1870. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1871. pmlmeext->tx_rate = rate;
  1872. DBG_8723A("%s(): rate = %x\n", __func__, rate);
  1873. }
  1874. void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
  1875. struct pkt_attrib *pattrib)
  1876. {
  1877. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1878. memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
  1879. pattrib->hdrlen = 24;
  1880. pattrib->nr_frags = 1;
  1881. pattrib->priority = 7;
  1882. pattrib->mac_id = 0;
  1883. pattrib->qsel = 0x12;
  1884. pattrib->pktlen = 0;
  1885. if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
  1886. pattrib->raid = 6;/* b mode */
  1887. else
  1888. pattrib->raid = 5;/* a/g mode */
  1889. pattrib->encrypt = 0;
  1890. pattrib->bswenc = false;
  1891. pattrib->qos_en = false;
  1892. pattrib->ht_en = false;
  1893. pattrib->bwmode = HT_CHANNEL_WIDTH_20;
  1894. pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  1895. pattrib->sgi = false;
  1896. pattrib->seqnum = pmlmeext->mgnt_seq;
  1897. pattrib->retry_ctrl = true;
  1898. }
  1899. void dump_mgntframe23a(struct rtw_adapter *padapter,
  1900. struct xmit_frame *pmgntframe)
  1901. {
  1902. if (padapter->bSurpriseRemoved == true ||
  1903. padapter->bDriverStopped == true)
  1904. return;
  1905. rtl8723au_mgnt_xmit(padapter, pmgntframe);
  1906. }
  1907. int dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
  1908. struct xmit_frame *pmgntframe, int timeout_ms)
  1909. {
  1910. int ret = _FAIL;
  1911. unsigned long irqL;
  1912. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1913. struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
  1914. struct submit_ctx sctx;
  1915. if (padapter->bSurpriseRemoved == true ||
  1916. padapter->bDriverStopped == true)
  1917. return ret;
  1918. rtw_sctx_init23a(&sctx, timeout_ms);
  1919. pxmitbuf->sctx = &sctx;
  1920. ret = rtl8723au_mgnt_xmit(padapter, pmgntframe);
  1921. if (ret == _SUCCESS)
  1922. ret = rtw_sctx_wait23a(&sctx);
  1923. spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
  1924. pxmitbuf->sctx = NULL;
  1925. spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
  1926. return ret;
  1927. }
  1928. int dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
  1929. struct xmit_frame *pmgntframe)
  1930. {
  1931. int ret = _FAIL;
  1932. u32 timeout_ms = 500;/* 500ms */
  1933. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1934. if (padapter->bSurpriseRemoved == true ||
  1935. padapter->bDriverStopped == true)
  1936. return _FAIL;
  1937. mutex_lock(&pxmitpriv->ack_tx_mutex);
  1938. pxmitpriv->ack_tx = true;
  1939. pmgntframe->ack_report = 1;
  1940. if (rtl8723au_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
  1941. ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
  1942. pxmitpriv->ack_tx = false;
  1943. mutex_unlock(&pxmitpriv->ack_tx_mutex);
  1944. return ret;
  1945. }
  1946. static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
  1947. {
  1948. u8 *ssid_ie;
  1949. int ssid_len_ori;
  1950. int len_diff = 0;
  1951. u8 *next_ie;
  1952. u32 remain_len;
  1953. ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
  1954. /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
  1955. __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
  1956. if (ssid_ie && ssid_len_ori > 0) {
  1957. switch (hidden_ssid_mode) {
  1958. case 1:
  1959. next_ie = ssid_ie + 2 + ssid_len_ori;
  1960. remain_len = ies_len -(next_ie-ies);
  1961. ssid_ie[1] = 0;
  1962. memcpy(ssid_ie+2, next_ie, remain_len);
  1963. len_diff -= ssid_len_ori;
  1964. break;
  1965. case 2:
  1966. memset(&ssid_ie[2], 0, ssid_len_ori);
  1967. break;
  1968. default:
  1969. break;
  1970. }
  1971. }
  1972. return len_diff;
  1973. }
  1974. void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
  1975. {
  1976. struct xmit_frame *pmgntframe;
  1977. struct pkt_attrib *pattrib;
  1978. unsigned char *pframe;
  1979. struct ieee80211_mgmt *mgmt;
  1980. unsigned int rate_len;
  1981. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  1982. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  1983. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  1984. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  1985. struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
  1986. u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  1987. const u8 *wps_ie;
  1988. u8 sr = 0;
  1989. int len_diff;
  1990. /* DBG_8723A("%s\n", __func__); */
  1991. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  1992. if (!pmgntframe) {
  1993. DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
  1994. return;
  1995. }
  1996. #ifdef CONFIG_8723AU_AP_MODE
  1997. spin_lock_bh(&pmlmepriv->bcn_update_lock);
  1998. #endif
  1999. /* update attribute */
  2000. pattrib = &pmgntframe->attrib;
  2001. update_mgntframe_attrib23a(padapter, pattrib);
  2002. pattrib->qsel = 0x10;
  2003. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2004. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  2005. mgmt = (struct ieee80211_mgmt *)pframe;
  2006. mgmt->frame_control =
  2007. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
  2008. mgmt->seq_ctrl = 0;
  2009. ether_addr_copy(mgmt->da, bc_addr);
  2010. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  2011. ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
  2012. /* timestamp will be inserted by hardware */
  2013. put_unaligned_le16(cur_network->beacon_interval,
  2014. &mgmt->u.beacon.beacon_int);
  2015. put_unaligned_le16(cur_network->capability,
  2016. &mgmt->u.beacon.capab_info);
  2017. pframe = mgmt->u.beacon.variable;
  2018. pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
  2019. if ((pmlmeinfo->state & 0x03) == MSR_AP) {
  2020. u8 *iebuf;
  2021. int buflen;
  2022. /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
  2023. memcpy(pframe, cur_network->IEs, cur_network->IELength);
  2024. len_diff = update_hidden_ssid(pframe, cur_network->IELength,
  2025. pmlmeinfo->hidden_ssid_mode);
  2026. pframe += (cur_network->IELength+len_diff);
  2027. pattrib->pktlen += (cur_network->IELength+len_diff);
  2028. iebuf = mgmt->u.beacon.variable;
  2029. buflen = pattrib->pktlen -
  2030. offsetof(struct ieee80211_mgmt, u.beacon.variable);
  2031. wps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
  2032. WLAN_OUI_TYPE_MICROSOFT_WPS,
  2033. iebuf, buflen);
  2034. if (wps_ie && wps_ie[1] > 0) {
  2035. rtw_get_wps_attr_content23a(wps_ie, wps_ie[1],
  2036. WPS_ATTR_SELECTED_REGISTRAR,
  2037. (u8 *)&sr);
  2038. }
  2039. if (sr != 0)
  2040. set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
  2041. else
  2042. _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
  2043. goto _issue_bcn;
  2044. }
  2045. /* SSID */
  2046. pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
  2047. cur_network->Ssid.ssid_len,
  2048. cur_network->Ssid.ssid, &pattrib->pktlen);
  2049. /* supported rates... */
  2050. rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
  2051. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
  2052. ((rate_len > 8)? 8: rate_len),
  2053. cur_network->SupportedRates, &pattrib->pktlen);
  2054. /* DS parameter set */
  2055. pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
  2056. &cur_network->DSConfig, &pattrib->pktlen);
  2057. /* if ((pmlmeinfo->state&0x03) == MSR_ADHOC) */
  2058. {
  2059. u8 erpinfo = 0;
  2060. u32 ATIMWindow;
  2061. /* IBSS Parameter Set... */
  2062. /* ATIMWindow = cur->ATIMWindow; */
  2063. ATIMWindow = 0;
  2064. pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
  2065. (unsigned char *)&ATIMWindow,
  2066. &pattrib->pktlen);
  2067. /* ERP IE */
  2068. pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
  2069. &erpinfo, &pattrib->pktlen);
  2070. }
  2071. /* EXTERNDED SUPPORTED RATE */
  2072. if (rate_len > 8)
  2073. pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
  2074. rate_len - 8,
  2075. cur_network->SupportedRates + 8,
  2076. &pattrib->pktlen);
  2077. /* todo:HT for adhoc */
  2078. _issue_bcn:
  2079. #ifdef CONFIG_8723AU_AP_MODE
  2080. pmlmepriv->update_bcn = false;
  2081. spin_unlock_bh(&pmlmepriv->bcn_update_lock);
  2082. #endif
  2083. if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
  2084. DBG_8723A("beacon frame too large\n");
  2085. return;
  2086. }
  2087. pattrib->last_txcmdsz = pattrib->pktlen;
  2088. /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
  2089. if (timeout_ms > 0)
  2090. dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
  2091. else
  2092. dump_mgntframe23a(padapter, pmgntframe);
  2093. }
  2094. static void issue_probersp(struct rtw_adapter *padapter, unsigned char *da)
  2095. {
  2096. struct xmit_frame *pmgntframe;
  2097. struct pkt_attrib *pattrib;
  2098. unsigned char *pframe;
  2099. struct ieee80211_mgmt *mgmt;
  2100. unsigned char *mac, *bssid;
  2101. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2102. #ifdef CONFIG_8723AU_AP_MODE
  2103. const u8 *pwps_ie;
  2104. u8 *ssid_ie;
  2105. int ssid_ielen;
  2106. int ssid_ielen_diff;
  2107. u8 buf[MAX_IE_SZ];
  2108. #endif
  2109. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2110. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2111. struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
  2112. unsigned int rate_len;
  2113. /* DBG_8723A("%s\n", __func__); */
  2114. if (cur_network->IELength > MAX_IE_SZ)
  2115. return;
  2116. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2117. if (!pmgntframe) {
  2118. DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
  2119. return;
  2120. }
  2121. /* update attribute */
  2122. pattrib = &pmgntframe->attrib;
  2123. update_mgntframe_attrib23a(padapter, pattrib);
  2124. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2125. pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
  2126. mgmt = (struct ieee80211_mgmt *)pframe;
  2127. mac = myid(&padapter->eeprompriv);
  2128. bssid = cur_network->MacAddress;
  2129. mgmt->frame_control =
  2130. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
  2131. ether_addr_copy(mgmt->da, da);
  2132. ether_addr_copy(mgmt->sa, mac);
  2133. ether_addr_copy(mgmt->bssid, bssid);
  2134. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2135. pmlmeext->mgnt_seq++;
  2136. pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
  2137. /* timestamp will be inserted by hardware */
  2138. put_unaligned_le16(cur_network->beacon_interval,
  2139. &mgmt->u.probe_resp.beacon_int);
  2140. put_unaligned_le16(cur_network->capability,
  2141. &mgmt->u.probe_resp.capab_info);
  2142. pframe = mgmt->u.probe_resp.variable;
  2143. pattrib->pktlen =
  2144. offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
  2145. /* below for ad-hoc mode */
  2146. #ifdef CONFIG_8723AU_AP_MODE
  2147. if ((pmlmeinfo->state & 0x03) == MSR_AP) {
  2148. pwps_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
  2149. WLAN_OUI_TYPE_MICROSOFT_WPS,
  2150. cur_network->IEs,
  2151. cur_network->IELength);
  2152. memcpy(pframe, cur_network->IEs, cur_network->IELength);
  2153. pframe += cur_network->IELength;
  2154. pattrib->pktlen += cur_network->IELength;
  2155. /* retrieve SSID IE from cur_network->Ssid */
  2156. ssid_ie = rtw_get_ie23a(mgmt->u.probe_resp.variable,
  2157. WLAN_EID_SSID, &ssid_ielen,
  2158. pframe - mgmt->u.probe_resp.variable);
  2159. ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
  2160. if (ssid_ie && cur_network->Ssid.ssid_len) {
  2161. uint remainder_ielen;
  2162. u8 *remainder_ie;
  2163. remainder_ie = ssid_ie + 2;
  2164. remainder_ielen = pframe - remainder_ie;
  2165. DBG_8723A_LEVEL(_drv_warning_, "%s(%s): "
  2166. "remainder_ielen > MAX_IE_SZ\n",
  2167. __func__, padapter->pnetdev->name);
  2168. if (remainder_ielen > MAX_IE_SZ)
  2169. remainder_ielen = MAX_IE_SZ;
  2170. memcpy(buf, remainder_ie, remainder_ielen);
  2171. memcpy(remainder_ie + ssid_ielen_diff, buf,
  2172. remainder_ielen);
  2173. *(ssid_ie + 1) = cur_network->Ssid.ssid_len;
  2174. memcpy(ssid_ie + 2, cur_network->Ssid.ssid,
  2175. cur_network->Ssid.ssid_len);
  2176. pframe += ssid_ielen_diff;
  2177. pattrib->pktlen += ssid_ielen_diff;
  2178. }
  2179. } else
  2180. #endif
  2181. {
  2182. /* SSID */
  2183. pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
  2184. cur_network->Ssid.ssid_len,
  2185. cur_network->Ssid.ssid,
  2186. &pattrib->pktlen);
  2187. /* supported rates... */
  2188. rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
  2189. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
  2190. ((rate_len > 8)? 8: rate_len),
  2191. cur_network->SupportedRates,
  2192. &pattrib->pktlen);
  2193. /* DS parameter set */
  2194. pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1,
  2195. (unsigned char *)&cur_network->DSConfig,
  2196. &pattrib->pktlen);
  2197. if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
  2198. u8 erpinfo = 0;
  2199. u32 ATIMWindow;
  2200. /* IBSS Parameter Set... */
  2201. /* ATIMWindow = cur->ATIMWindow; */
  2202. ATIMWindow = 0;
  2203. pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
  2204. (unsigned char *)&ATIMWindow,
  2205. &pattrib->pktlen);
  2206. /* ERP IE */
  2207. pframe = rtw_set_ie23a(pframe, WLAN_EID_ERP_INFO, 1,
  2208. &erpinfo, &pattrib->pktlen);
  2209. }
  2210. /* EXTERNDED SUPPORTED RATE */
  2211. if (rate_len > 8)
  2212. pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
  2213. rate_len - 8,
  2214. cur_network->SupportedRates + 8,
  2215. &pattrib->pktlen);
  2216. /* todo:HT for adhoc */
  2217. }
  2218. pattrib->last_txcmdsz = pattrib->pktlen;
  2219. dump_mgntframe23a(padapter, pmgntframe);
  2220. }
  2221. static int _issue_probereq(struct rtw_adapter *padapter,
  2222. struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
  2223. {
  2224. int ret = _FAIL;
  2225. struct xmit_frame *pmgntframe;
  2226. struct pkt_attrib *pattrib;
  2227. unsigned char *pframe;
  2228. struct ieee80211_hdr *pwlanhdr;
  2229. unsigned char *mac;
  2230. unsigned char bssrate[NumRates];
  2231. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2232. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  2233. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2234. int bssrate_len = 0;
  2235. u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  2236. RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
  2237. "+%s\n", __func__);
  2238. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2239. if (!pmgntframe)
  2240. goto exit;
  2241. /* update attribute */
  2242. pattrib = &pmgntframe->attrib;
  2243. update_mgntframe_attrib23a(padapter, pattrib);
  2244. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2245. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  2246. pwlanhdr = (struct ieee80211_hdr *)pframe;
  2247. mac = myid(&padapter->eeprompriv);
  2248. pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
  2249. IEEE80211_STYPE_PROBE_REQ);
  2250. if (da) {
  2251. /* unicast probe request frame */
  2252. ether_addr_copy(pwlanhdr->addr1, da);
  2253. ether_addr_copy(pwlanhdr->addr3, da);
  2254. } else {
  2255. /* broadcast probe request frame */
  2256. ether_addr_copy(pwlanhdr->addr1, bc_addr);
  2257. ether_addr_copy(pwlanhdr->addr3, bc_addr);
  2258. }
  2259. ether_addr_copy(pwlanhdr->addr2, mac);
  2260. pwlanhdr->seq_ctrl =
  2261. cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2262. pmlmeext->mgnt_seq++;
  2263. pframe += sizeof (struct ieee80211_hdr_3addr);
  2264. pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
  2265. if (pssid)
  2266. pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, pssid->ssid_len,
  2267. pssid->ssid, &pattrib->pktlen);
  2268. else
  2269. pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID, 0, NULL,
  2270. &pattrib->pktlen);
  2271. get_rate_set23a(padapter, bssrate, &bssrate_len);
  2272. if (bssrate_len > 8) {
  2273. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
  2274. bssrate, &pattrib->pktlen);
  2275. pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
  2276. (bssrate_len - 8), (bssrate + 8),
  2277. &pattrib->pktlen);
  2278. } else {
  2279. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
  2280. bssrate_len, bssrate, &pattrib->pktlen);
  2281. }
  2282. /* add wps_ie for wps2.0 */
  2283. if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
  2284. memcpy(pframe, pmlmepriv->wps_probe_req_ie,
  2285. pmlmepriv->wps_probe_req_ie_len);
  2286. pframe += pmlmepriv->wps_probe_req_ie_len;
  2287. pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
  2288. }
  2289. pattrib->last_txcmdsz = pattrib->pktlen;
  2290. RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
  2291. "issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz);
  2292. if (wait_ack) {
  2293. ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
  2294. } else {
  2295. dump_mgntframe23a(padapter, pmgntframe);
  2296. ret = _SUCCESS;
  2297. }
  2298. exit:
  2299. return ret;
  2300. }
  2301. static inline void issue_probereq(struct rtw_adapter *padapter,
  2302. struct cfg80211_ssid *pssid, u8 *da)
  2303. {
  2304. _issue_probereq(padapter, pssid, da, false);
  2305. }
  2306. static int issue_probereq_ex(struct rtw_adapter *padapter,
  2307. struct cfg80211_ssid *pssid, u8 *da,
  2308. int try_cnt, int wait_ms)
  2309. {
  2310. int ret;
  2311. int i = 0;
  2312. unsigned long start = jiffies;
  2313. do {
  2314. ret = _issue_probereq(padapter, pssid, da,
  2315. wait_ms > 0 ? true : false);
  2316. i++;
  2317. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  2318. break;
  2319. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  2320. msleep(wait_ms);
  2321. } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
  2322. if (ret != _FAIL) {
  2323. ret = _SUCCESS;
  2324. goto exit;
  2325. }
  2326. if (try_cnt && wait_ms) {
  2327. if (da)
  2328. DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
  2329. __func__, padapter->pnetdev->name,
  2330. da, rtw_get_oper_ch23a(padapter),
  2331. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  2332. jiffies_to_msecs(jiffies - start));
  2333. else
  2334. DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
  2335. __func__, padapter->pnetdev->name,
  2336. rtw_get_oper_ch23a(padapter),
  2337. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  2338. jiffies_to_msecs(jiffies - start));
  2339. }
  2340. exit:
  2341. return ret;
  2342. }
  2343. /* if psta == NULL, indiate we are station(client) now... */
  2344. static void issue_auth(struct rtw_adapter *padapter, struct sta_info *psta,
  2345. unsigned short status)
  2346. {
  2347. struct xmit_frame *pmgntframe;
  2348. struct pkt_attrib *pattrib;
  2349. unsigned char *pframe;
  2350. struct ieee80211_mgmt *mgmt;
  2351. unsigned int val32;
  2352. u16 auth_algo;
  2353. int use_shared_key = 0;
  2354. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2355. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2356. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2357. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2358. if (!pmgntframe)
  2359. return;
  2360. /* update attribute */
  2361. pattrib = &pmgntframe->attrib;
  2362. update_mgntframe_attrib23a(padapter, pattrib);
  2363. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2364. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  2365. mgmt = (struct ieee80211_mgmt *)pframe;
  2366. mgmt->frame_control =
  2367. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
  2368. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2369. pmlmeext->mgnt_seq++;
  2370. pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.auth.variable);
  2371. if (psta) { /* for AP mode */
  2372. #ifdef CONFIG_8723AU_AP_MODE
  2373. unsigned short val16;
  2374. ether_addr_copy(mgmt->da, psta->hwaddr);
  2375. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  2376. ether_addr_copy(mgmt->bssid, myid(&padapter->eeprompriv));
  2377. /* setting auth algo number */
  2378. val16 = (u16)psta->authalg;
  2379. if (status != WLAN_STATUS_SUCCESS)
  2380. val16 = 0;
  2381. if (val16)
  2382. use_shared_key = 1;
  2383. mgmt->u.auth.auth_alg = cpu_to_le16(val16);
  2384. /* setting auth seq number */
  2385. mgmt->u.auth.auth_transaction =
  2386. cpu_to_le16((u16)psta->auth_seq);
  2387. /* setting status code... */
  2388. mgmt->u.auth.status_code = cpu_to_le16(status);
  2389. pframe = mgmt->u.auth.variable;
  2390. /* added challenging text... */
  2391. if ((psta->auth_seq == 2) &&
  2392. (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
  2393. pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
  2394. psta->chg_txt, &pattrib->pktlen);
  2395. #endif
  2396. } else {
  2397. struct ieee80211_mgmt *iv_mgmt;
  2398. ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
  2399. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  2400. ether_addr_copy(mgmt->bssid,
  2401. get_my_bssid23a(&pmlmeinfo->network));
  2402. /* setting auth algo number */
  2403. /* 0:OPEN System, 1:Shared key */
  2404. if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
  2405. use_shared_key = 1;
  2406. auth_algo = WLAN_AUTH_SHARED_KEY;
  2407. } else
  2408. auth_algo = WLAN_AUTH_OPEN;
  2409. /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
  2410. (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
  2411. pmlmeinfo->auth_seq); */
  2412. /* setting IV for auth seq #3 */
  2413. if ((pmlmeinfo->auth_seq == 3) &&
  2414. (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
  2415. (use_shared_key == 1)) {
  2416. u32 *piv = (u32 *)&mgmt->u.auth;
  2417. iv_mgmt = (struct ieee80211_mgmt *)(pframe + 4);
  2418. /* DBG_8723A("==> iv(%d), key_index(%d)\n",
  2419. pmlmeinfo->iv, pmlmeinfo->key_index); */
  2420. val32 = (pmlmeinfo->iv & 0x3fffffff) |
  2421. (pmlmeinfo->key_index << 30);
  2422. pmlmeinfo->iv++;
  2423. put_unaligned_le32(val32, piv);
  2424. pattrib->pktlen += 4;
  2425. pattrib->iv_len = IEEE80211_WEP_IV_LEN;
  2426. } else
  2427. iv_mgmt = mgmt;
  2428. iv_mgmt->u.auth.auth_alg = cpu_to_le16(auth_algo);
  2429. /* setting auth seq number */
  2430. iv_mgmt->u.auth.auth_transaction =
  2431. cpu_to_le16(pmlmeinfo->auth_seq);
  2432. /* setting status code... */
  2433. iv_mgmt->u.auth.status_code = cpu_to_le16(status);
  2434. pframe = iv_mgmt->u.auth.variable;
  2435. /* then checking to see if sending challenging text... */
  2436. if ((pmlmeinfo->auth_seq == 3) &&
  2437. (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
  2438. (use_shared_key == 1)) {
  2439. pframe = rtw_set_ie23a(pframe, WLAN_EID_CHALLENGE, 128,
  2440. pmlmeinfo->chg_txt,
  2441. &pattrib->pktlen);
  2442. mgmt->frame_control |=
  2443. cpu_to_le16(IEEE80211_FCTL_PROTECTED);
  2444. pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
  2445. pattrib->encrypt = WLAN_CIPHER_SUITE_WEP40;
  2446. pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
  2447. pattrib->pktlen += pattrib->icv_len;
  2448. }
  2449. }
  2450. pattrib->last_txcmdsz = pattrib->pktlen;
  2451. rtw_wep_encrypt23a(padapter, pmgntframe);
  2452. DBG_8723A("%s\n", __func__);
  2453. dump_mgntframe23a(padapter, pmgntframe);
  2454. }
  2455. #ifdef CONFIG_8723AU_AP_MODE
  2456. static void issue_assocrsp(struct rtw_adapter *padapter, unsigned short status,
  2457. struct sta_info *pstat, u16 pkt_type)
  2458. {
  2459. struct xmit_frame *pmgntframe;
  2460. struct ieee80211_mgmt *mgmt;
  2461. struct pkt_attrib *pattrib;
  2462. unsigned char *pframe;
  2463. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2464. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  2465. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2466. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2467. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  2468. const u8 *p;
  2469. u8 *ie = pnetwork->IEs;
  2470. DBG_8723A("%s\n", __func__);
  2471. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2472. if (!pmgntframe)
  2473. return;
  2474. /* update attribute */
  2475. pattrib = &pmgntframe->attrib;
  2476. update_mgntframe_attrib23a(padapter, pattrib);
  2477. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2478. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  2479. mgmt = (struct ieee80211_mgmt *)pframe;
  2480. mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | pkt_type);
  2481. ether_addr_copy(mgmt->da, pstat->hwaddr);
  2482. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  2483. ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
  2484. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2485. pmlmeext->mgnt_seq++;
  2486. pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
  2487. pattrib->pktlen =
  2488. offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
  2489. mgmt->u.assoc_resp.capab_info = cpu_to_le16(pnetwork->capability);
  2490. mgmt->u.assoc_resp.status_code = cpu_to_le16(status);
  2491. mgmt->u.assoc_resp.aid = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
  2492. pframe = mgmt->u.assoc_resp.variable;
  2493. if (pstat->bssratelen <= 8) {
  2494. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
  2495. pstat->bssratelen, pstat->bssrateset,
  2496. &pattrib->pktlen);
  2497. } else {
  2498. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
  2499. pstat->bssrateset, &pattrib->pktlen);
  2500. pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
  2501. pstat->bssratelen - 8,
  2502. pstat->bssrateset + 8, &pattrib->pktlen);
  2503. }
  2504. if (pstat->flags & WLAN_STA_HT && pmlmepriv->htpriv.ht_option) {
  2505. /* FILL HT CAP INFO IE */
  2506. /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
  2507. p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ie,
  2508. pnetwork->IELength);
  2509. if (p && p[1]) {
  2510. memcpy(pframe, p, p[1] + 2);
  2511. pframe += (p[1] + 2);
  2512. pattrib->pktlen += (p[1] + 2);
  2513. }
  2514. /* FILL HT ADD INFO IE */
  2515. /* p = hostapd_eid_ht_operation(hapd, p); */
  2516. p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie,
  2517. pnetwork->IELength);
  2518. if (p && p[1] > 0) {
  2519. memcpy(pframe, p, p[1] + 2);
  2520. pframe += (p[1] + 2);
  2521. pattrib->pktlen += (p[1] + 2);
  2522. }
  2523. }
  2524. /* FILL WMM IE */
  2525. if (pstat->flags & WLAN_STA_WME && pmlmepriv->qos_option) {
  2526. unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
  2527. 0x01, 0x01};
  2528. int ie_len = 0;
  2529. for (p = ie; ; p += (ie_len + 2)) {
  2530. p = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, p,
  2531. pnetwork->IELength - (ie_len + 2));
  2532. if (p)
  2533. ie_len = p[1];
  2534. else
  2535. ie_len = 0;
  2536. if (p && !memcmp(p + 2, WMM_PARA_IE, 6)) {
  2537. memcpy(pframe, p, ie_len + 2);
  2538. pframe += (ie_len + 2);
  2539. pattrib->pktlen += (ie_len + 2);
  2540. break;
  2541. }
  2542. if (!p || ie_len == 0)
  2543. break;
  2544. }
  2545. }
  2546. if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
  2547. pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
  2548. REALTEK_96B_IE, &pattrib->pktlen);
  2549. }
  2550. pattrib->last_txcmdsz = pattrib->pktlen;
  2551. dump_mgntframe23a(padapter, pmgntframe);
  2552. }
  2553. #endif
  2554. static void issue_assocreq(struct rtw_adapter *padapter)
  2555. {
  2556. int ret = _FAIL;
  2557. struct xmit_frame *pmgntframe;
  2558. struct pkt_attrib *pattrib;
  2559. unsigned char *pframe;
  2560. const u8 *p;
  2561. struct ieee80211_mgmt *mgmt;
  2562. unsigned int i, j, index = 0;
  2563. unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
  2564. struct registry_priv *pregpriv = &padapter->registrypriv;
  2565. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2566. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  2567. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2568. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2569. int bssrate_len = 0, sta_bssrate_len = 0, pie_len;
  2570. u8 *pie;
  2571. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2572. if (!pmgntframe)
  2573. goto exit;
  2574. /* update attribute */
  2575. pattrib = &pmgntframe->attrib;
  2576. update_mgntframe_attrib23a(padapter, pattrib);
  2577. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2578. pframe = (u8 *)pmgntframe->buf_addr + TXDESC_OFFSET;
  2579. mgmt = (struct ieee80211_mgmt *)pframe;
  2580. mgmt->frame_control =
  2581. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ASSOC_REQ);
  2582. ether_addr_copy(mgmt->da, get_my_bssid23a(&pmlmeinfo->network));
  2583. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  2584. ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
  2585. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2586. pmlmeext->mgnt_seq++;
  2587. /* caps */
  2588. put_unaligned_le16(pmlmeinfo->network.capability,
  2589. &mgmt->u.assoc_req.capab_info);
  2590. /* todo: listen interval for power saving */
  2591. put_unaligned_le16(3, &mgmt->u.assoc_req.listen_interval);
  2592. pframe = mgmt->u.assoc_req.variable;
  2593. pattrib->pktlen = offsetof(struct ieee80211_mgmt, u.assoc_req.variable);
  2594. /* SSID */
  2595. pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
  2596. pmlmeinfo->network.Ssid.ssid_len,
  2597. pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
  2598. /* supported rate & extended supported rate */
  2599. get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
  2600. /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
  2601. /* for JAPAN, channel 14 can only uses B Mode(CCK) */
  2602. if (pmlmeext->cur_channel == 14)
  2603. sta_bssrate_len = 4;
  2604. /* for (i = 0; i < sta_bssrate_len; i++) { */
  2605. /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
  2606. /* */
  2607. for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
  2608. if (pmlmeinfo->network.SupportedRates[i] == 0)
  2609. break;
  2610. DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
  2611. pmlmeinfo->network.SupportedRates[i]);
  2612. }
  2613. for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
  2614. if (pmlmeinfo->network.SupportedRates[i] == 0)
  2615. break;
  2616. /* Check if the AP's supported rates are also
  2617. supported by STA. */
  2618. for (j = 0; j < sta_bssrate_len; j++) {
  2619. /* Avoid the proprietary data rate (22Mbps) of
  2620. Handlink WSG-4000 AP */
  2621. if ((pmlmeinfo->network.SupportedRates[i] |
  2622. IEEE80211_BASIC_RATE_MASK) ==
  2623. (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {
  2624. /* DBG_8723A("match i = %d, j =%d\n", i, j); */
  2625. break;
  2626. }
  2627. }
  2628. if (j == sta_bssrate_len) {
  2629. /* the rate is not supported by STA */
  2630. DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
  2631. "STA!\n", __func__, i,
  2632. pmlmeinfo->network.SupportedRates[i]);
  2633. } else {
  2634. /* the rate is supported by STA */
  2635. bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
  2636. }
  2637. }
  2638. bssrate_len = index;
  2639. DBG_8723A("bssrate_len = %d\n", bssrate_len);
  2640. if (bssrate_len == 0) {
  2641. rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
  2642. rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
  2643. goto exit; /* don't connect to AP if no joint supported rate */
  2644. }
  2645. if (bssrate_len > 8) {
  2646. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, 8,
  2647. bssrate, &pattrib->pktlen);
  2648. pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
  2649. (bssrate_len - 8), (bssrate + 8),
  2650. &pattrib->pktlen);
  2651. } else
  2652. pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES,
  2653. bssrate_len, bssrate, &pattrib->pktlen);
  2654. /* RSN */
  2655. pie = pmlmeinfo->network.IEs;
  2656. pie_len = pmlmeinfo->network.IELength;
  2657. p = cfg80211_find_ie(WLAN_EID_RSN, pie, pie_len);
  2658. if (p)
  2659. pframe = rtw_set_ie23a(pframe, WLAN_EID_RSN, p[1], p + 2,
  2660. &pattrib->pktlen);
  2661. /* HT caps */
  2662. if (padapter->mlmepriv.htpriv.ht_option) {
  2663. p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, pie, pie_len);
  2664. if (p && !is_ap_in_tkip23a(padapter)) {
  2665. struct ieee80211_ht_cap *cap = &pmlmeinfo->ht_cap;
  2666. memcpy(cap, p + 2, sizeof(struct ieee80211_ht_cap));
  2667. /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
  2668. if (pregpriv->cbw40_enable == 0) {
  2669. cap->cap_info &= ~cpu_to_le16(
  2670. IEEE80211_HT_CAP_SGI_40 |
  2671. IEEE80211_HT_CAP_SUP_WIDTH_20_40);
  2672. } else {
  2673. cap->cap_info |= cpu_to_le16(
  2674. IEEE80211_HT_CAP_SUP_WIDTH_20_40);
  2675. }
  2676. /* todo: disable SM power save mode */
  2677. cap->cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
  2678. rf_type = rtl8723a_get_rf_type(padapter);
  2679. /* switch (pregpriv->rf_config) */
  2680. switch (rf_type) {
  2681. case RF_1T1R:
  2682. /* RX STBC One spatial stream */
  2683. if (pregpriv->rx_stbc)
  2684. cap->cap_info |= cpu_to_le16(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
  2685. memcpy(&cap->mcs, MCS_rate_1R23A, 16);
  2686. break;
  2687. case RF_2T2R:
  2688. case RF_1T2R:
  2689. default:
  2690. /* enable for 2.4/5 GHz */
  2691. if (pregpriv->rx_stbc == 0x3 ||
  2692. (pmlmeext->cur_wireless_mode &
  2693. WIRELESS_11_24N &&
  2694. /* enable for 2.4GHz */
  2695. pregpriv->rx_stbc == 0x1) ||
  2696. (pmlmeext->cur_wireless_mode &
  2697. WIRELESS_11_5N &&
  2698. pregpriv->rx_stbc == 0x2) ||
  2699. /* enable for 5GHz */
  2700. pregpriv->wifi_spec == 1) {
  2701. DBG_8723A("declare supporting RX "
  2702. "STBC\n");
  2703. /* RX STBC two spatial stream */
  2704. cap->cap_info |= cpu_to_le16(2 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
  2705. }
  2706. memcpy(&cap->mcs, MCS_rate_2R23A, 16);
  2707. break;
  2708. }
  2709. if (rtl8723a_BT_coexist(padapter) &&
  2710. rtl8723a_BT_using_antenna_1(padapter)) {
  2711. /* set to 8K */
  2712. cap->ampdu_params_info &=
  2713. ~IEEE80211_HT_AMPDU_PARM_FACTOR;
  2714. /* cap->ampdu_params_info |= MAX_AMPDU_FACTOR_8K */
  2715. }
  2716. pframe = rtw_set_ie23a(pframe, WLAN_EID_HT_CAPABILITY,
  2717. p[1], (u8 *)&pmlmeinfo->ht_cap,
  2718. &pattrib->pktlen);
  2719. }
  2720. }
  2721. /* vendor specific IE, such as WPA, WMM, WPS */
  2722. for (i = 0; i < pmlmeinfo->network.IELength;) {
  2723. p = pmlmeinfo->network.IEs + i;
  2724. switch (p[0]) {
  2725. case WLAN_EID_VENDOR_SPECIFIC:
  2726. if (!memcmp(p + 2, RTW_WPA_OUI23A_TYPE, 4) ||
  2727. !memcmp(p + 2, WMM_OUI23A, 4) ||
  2728. !memcmp(p + 2, WPS_OUI23A, 4)) {
  2729. u8 plen = p[1];
  2730. if (!padapter->registrypriv.wifi_spec) {
  2731. /* Commented by Kurt 20110629 */
  2732. /* In some older APs, WPS handshake */
  2733. /* would be fail if we append vender
  2734. extensions informations to AP */
  2735. if (!memcmp(p + 2, WPS_OUI23A, 4))
  2736. plen = 14;
  2737. }
  2738. pframe = rtw_set_ie23a(pframe,
  2739. WLAN_EID_VENDOR_SPECIFIC,
  2740. plen, p + 2,
  2741. &pattrib->pktlen);
  2742. }
  2743. break;
  2744. default:
  2745. break;
  2746. }
  2747. i += p[1] + 2;
  2748. }
  2749. if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
  2750. pframe = rtw_set_ie23a(pframe, WLAN_EID_VENDOR_SPECIFIC, 6,
  2751. REALTEK_96B_IE, &pattrib->pktlen);
  2752. pattrib->last_txcmdsz = pattrib->pktlen;
  2753. dump_mgntframe23a(padapter, pmgntframe);
  2754. ret = _SUCCESS;
  2755. exit:
  2756. pmlmepriv->assoc_req_len = 0;
  2757. if (ret == _SUCCESS) {
  2758. kfree(pmlmepriv->assoc_req);
  2759. pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
  2760. if (pmlmepriv->assoc_req) {
  2761. memcpy(pmlmepriv->assoc_req, mgmt, pattrib->pktlen);
  2762. pmlmepriv->assoc_req_len = pattrib->pktlen;
  2763. }
  2764. } else
  2765. kfree(pmlmepriv->assoc_req);
  2766. }
  2767. /* when wait_ack is true, this function should be called at process context */
  2768. static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
  2769. unsigned int power_mode, int wait_ack)
  2770. {
  2771. int ret = _FAIL;
  2772. struct xmit_frame *pmgntframe;
  2773. struct pkt_attrib *pattrib;
  2774. unsigned char *pframe;
  2775. struct ieee80211_hdr *pwlanhdr;
  2776. struct xmit_priv *pxmitpriv;
  2777. struct mlme_ext_priv *pmlmeext;
  2778. struct mlme_ext_info *pmlmeinfo;
  2779. /* DBG_8723A("%s:%d\n", __func__, power_mode); */
  2780. if (!padapter)
  2781. goto exit;
  2782. pxmitpriv = &padapter->xmitpriv;
  2783. pmlmeext = &padapter->mlmeextpriv;
  2784. pmlmeinfo = &pmlmeext->mlmext_info;
  2785. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2786. if (!pmgntframe)
  2787. goto exit;
  2788. /* update attribute */
  2789. pattrib = &pmgntframe->attrib;
  2790. update_mgntframe_attrib23a(padapter, pattrib);
  2791. pattrib->retry_ctrl = false;
  2792. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2793. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  2794. pwlanhdr = (struct ieee80211_hdr *)pframe;
  2795. pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
  2796. IEEE80211_STYPE_NULLFUNC);
  2797. if ((pmlmeinfo->state&0x03) == MSR_AP)
  2798. pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
  2799. else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
  2800. pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
  2801. if (power_mode)
  2802. pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
  2803. ether_addr_copy(pwlanhdr->addr1, da);
  2804. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  2805. ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
  2806. pwlanhdr->seq_ctrl =
  2807. cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2808. pmlmeext->mgnt_seq++;
  2809. pframe += sizeof(struct ieee80211_hdr_3addr);
  2810. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
  2811. pattrib->last_txcmdsz = pattrib->pktlen;
  2812. if (wait_ack)
  2813. ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
  2814. else {
  2815. dump_mgntframe23a(padapter, pmgntframe);
  2816. ret = _SUCCESS;
  2817. }
  2818. exit:
  2819. return ret;
  2820. }
  2821. /* when wait_ms >0 , this function should be called at process context */
  2822. /* da == NULL for station mode */
  2823. int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
  2824. unsigned int power_mode, int try_cnt, int wait_ms)
  2825. {
  2826. int ret;
  2827. int i = 0;
  2828. unsigned long start = jiffies;
  2829. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2830. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2831. /* da == NULL, assume it's null data for sta to ap*/
  2832. if (da == NULL)
  2833. da = get_my_bssid23a(&pmlmeinfo->network);
  2834. do {
  2835. ret = _issue_nulldata23a(padapter, da, power_mode,
  2836. wait_ms > 0 ? true : false);
  2837. i++;
  2838. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  2839. break;
  2840. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  2841. msleep(wait_ms);
  2842. } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
  2843. if (ret != _FAIL) {
  2844. ret = _SUCCESS;
  2845. goto exit;
  2846. }
  2847. if (try_cnt && wait_ms) {
  2848. if (da)
  2849. DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
  2850. __func__, padapter->pnetdev->name,
  2851. da, rtw_get_oper_ch23a(padapter),
  2852. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  2853. jiffies_to_msecs(jiffies - start));
  2854. else
  2855. DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
  2856. __func__, padapter->pnetdev->name,
  2857. rtw_get_oper_ch23a(padapter),
  2858. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  2859. jiffies_to_msecs(jiffies - start));
  2860. }
  2861. exit:
  2862. return ret;
  2863. }
  2864. /* when wait_ack is true, this function should be called at process context */
  2865. static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
  2866. unsigned char *da, u16 tid, int wait_ack)
  2867. {
  2868. int ret = _FAIL;
  2869. struct xmit_frame *pmgntframe;
  2870. struct pkt_attrib *pattrib;
  2871. unsigned char *pframe;
  2872. struct ieee80211_qos_hdr *pwlanhdr;
  2873. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2874. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2875. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2876. DBG_8723A("%s\n", __func__);
  2877. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2878. if (!pmgntframe)
  2879. goto exit;
  2880. /* update attribute */
  2881. pattrib = &pmgntframe->attrib;
  2882. update_mgntframe_attrib23a(padapter, pattrib);
  2883. pattrib->hdrlen += 2;
  2884. pattrib->qos_en = true;
  2885. pattrib->eosp = 1;
  2886. pattrib->ack_policy = 0;
  2887. pattrib->mdata = 0;
  2888. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2889. pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
  2890. pwlanhdr = (struct ieee80211_qos_hdr *)pframe;
  2891. pwlanhdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
  2892. IEEE80211_STYPE_QOS_NULLFUNC);
  2893. if ((pmlmeinfo->state&0x03) == MSR_AP)
  2894. pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
  2895. else if ((pmlmeinfo->state&0x03) == MSR_INFRA)
  2896. pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
  2897. if (pattrib->mdata)
  2898. pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
  2899. pwlanhdr->qos_ctrl = cpu_to_le16(tid & IEEE80211_QOS_CTL_TID_MASK);
  2900. pwlanhdr->qos_ctrl |= cpu_to_le16((pattrib->ack_policy << 5) &
  2901. IEEE80211_QOS_CTL_ACK_POLICY_MASK);
  2902. if (pattrib->eosp)
  2903. pwlanhdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
  2904. ether_addr_copy(pwlanhdr->addr1, da);
  2905. ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
  2906. ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
  2907. pwlanhdr->seq_ctrl =
  2908. cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2909. pmlmeext->mgnt_seq++;
  2910. pframe += sizeof(struct ieee80211_qos_hdr);
  2911. pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
  2912. pattrib->last_txcmdsz = pattrib->pktlen;
  2913. if (wait_ack)
  2914. ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
  2915. else {
  2916. dump_mgntframe23a(padapter, pmgntframe);
  2917. ret = _SUCCESS;
  2918. }
  2919. exit:
  2920. return ret;
  2921. }
  2922. /* when wait_ms >0 , this function should be called at process context */
  2923. /* da == NULL for station mode */
  2924. int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
  2925. u16 tid, int try_cnt, int wait_ms)
  2926. {
  2927. int ret;
  2928. int i = 0;
  2929. unsigned long start = jiffies;
  2930. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2931. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2932. /* da == NULL, assume it's null data for sta to ap*/
  2933. if (da == NULL)
  2934. da = get_my_bssid23a(&pmlmeinfo->network);
  2935. do {
  2936. ret = _issue_qos_nulldata23a(padapter, da, tid,
  2937. wait_ms > 0 ? true : false);
  2938. i++;
  2939. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  2940. break;
  2941. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  2942. msleep(wait_ms);
  2943. } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
  2944. if (ret != _FAIL) {
  2945. ret = _SUCCESS;
  2946. goto exit;
  2947. }
  2948. if (try_cnt && wait_ms) {
  2949. if (da)
  2950. DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
  2951. __func__, padapter->pnetdev->name,
  2952. da, rtw_get_oper_ch23a(padapter),
  2953. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  2954. jiffies_to_msecs(jiffies - start));
  2955. else
  2956. DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
  2957. __func__, padapter->pnetdev->name,
  2958. rtw_get_oper_ch23a(padapter),
  2959. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  2960. jiffies_to_msecs(jiffies - start));
  2961. }
  2962. exit:
  2963. return ret;
  2964. }
  2965. static int _issue_deauth(struct rtw_adapter *padapter, unsigned char *da,
  2966. unsigned short reason, u8 wait_ack)
  2967. {
  2968. struct xmit_frame *pmgntframe;
  2969. struct pkt_attrib *pattrib;
  2970. struct ieee80211_mgmt *mgmt;
  2971. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  2972. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  2973. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  2974. int ret = _FAIL;
  2975. /* DBG_8723A("%s to %pM\n", __func__, da); */
  2976. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  2977. if (!pmgntframe)
  2978. goto exit;
  2979. /* update attribute */
  2980. pattrib = &pmgntframe->attrib;
  2981. update_mgntframe_attrib23a(padapter, pattrib);
  2982. pattrib->retry_ctrl = false;
  2983. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  2984. mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
  2985. mgmt->frame_control =
  2986. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH);
  2987. ether_addr_copy(mgmt->da, da);
  2988. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  2989. ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
  2990. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  2991. pmlmeext->mgnt_seq++;
  2992. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 2;
  2993. mgmt->u.deauth.reason_code = cpu_to_le16(reason);
  2994. pattrib->last_txcmdsz = pattrib->pktlen;
  2995. if (wait_ack)
  2996. ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
  2997. else {
  2998. dump_mgntframe23a(padapter, pmgntframe);
  2999. ret = _SUCCESS;
  3000. }
  3001. exit:
  3002. return ret;
  3003. }
  3004. int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
  3005. unsigned short reason)
  3006. {
  3007. DBG_8723A("%s to %pM\n", __func__, da);
  3008. return _issue_deauth(padapter, da, reason, false);
  3009. }
  3010. static int issue_deauth_ex(struct rtw_adapter *padapter, u8 *da,
  3011. unsigned short reason, int try_cnt, int wait_ms)
  3012. {
  3013. int ret;
  3014. int i = 0;
  3015. unsigned long start = jiffies;
  3016. do {
  3017. ret = _issue_deauth(padapter, da, reason,
  3018. wait_ms >0 ? true : false);
  3019. i++;
  3020. if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
  3021. break;
  3022. if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
  3023. msleep(wait_ms);
  3024. } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
  3025. if (ret != _FAIL) {
  3026. ret = _SUCCESS;
  3027. goto exit;
  3028. }
  3029. if (try_cnt && wait_ms) {
  3030. if (da)
  3031. DBG_8723A("%s(%s): to %pM, ch:%u%s, %d/%d in %u ms\n",
  3032. __func__, padapter->pnetdev->name,
  3033. da, rtw_get_oper_ch23a(padapter),
  3034. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  3035. jiffies_to_msecs(jiffies - start));
  3036. else
  3037. DBG_8723A("%s(%s):, ch:%u%s, %d/%d in %u ms\n",
  3038. __func__, padapter->pnetdev->name,
  3039. rtw_get_oper_ch23a(padapter),
  3040. ret == _SUCCESS ? ", acked" : "", i, try_cnt,
  3041. jiffies_to_msecs(jiffies - start));
  3042. }
  3043. exit:
  3044. return ret;
  3045. }
  3046. void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
  3047. u8 *ra, u8 new_ch, u8 ch_offset)
  3048. {
  3049. struct xmit_frame *pmgntframe;
  3050. struct pkt_attrib *pattrib;
  3051. unsigned char *pframe;
  3052. struct ieee80211_mgmt *mgmt;
  3053. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  3054. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3055. DBG_8723A("%s(%s): ra=%pM, ch:%u, offset:%u\n",
  3056. __func__, padapter->pnetdev->name, ra, new_ch, ch_offset);
  3057. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  3058. if (!pmgntframe)
  3059. return;
  3060. /* update attribute */
  3061. pattrib = &pmgntframe->attrib;
  3062. update_mgntframe_attrib23a(padapter, pattrib);
  3063. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  3064. mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
  3065. mgmt->frame_control =
  3066. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
  3067. ether_addr_copy(mgmt->da, ra); /* RA */
  3068. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv)); /* TA */
  3069. ether_addr_copy(mgmt->bssid, ra); /* DA = RA */
  3070. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  3071. pmlmeext->mgnt_seq++;
  3072. mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
  3073. mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
  3074. pframe = mgmt->u.action.u.chan_switch.variable;
  3075. pattrib->pktlen = offsetof(struct ieee80211_mgmt,
  3076. u.action.u.chan_switch.variable);
  3077. pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
  3078. new_ch, 0);
  3079. pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
  3080. hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
  3081. pattrib->last_txcmdsz = pattrib->pktlen;
  3082. dump_mgntframe23a(padapter, pmgntframe);
  3083. }
  3084. void issue_action_BA23a(struct rtw_adapter *padapter,
  3085. const unsigned char *raddr,
  3086. unsigned char action, unsigned short status)
  3087. {
  3088. u16 start_seq;
  3089. u16 BA_para_set;
  3090. u16 BA_starting_seqctrl;
  3091. u16 BA_para;
  3092. int max_rx_ampdu_factor;
  3093. struct xmit_frame *pmgntframe;
  3094. struct pkt_attrib *pattrib;
  3095. struct ieee80211_mgmt *mgmt;
  3096. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  3097. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3098. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3099. struct sta_info *psta;
  3100. struct sta_priv *pstapriv = &padapter->stapriv;
  3101. struct registry_priv *pregpriv = &padapter->registrypriv;
  3102. u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
  3103. DBG_8723A("%s, action =%d, status =%d\n", __func__, action, status);
  3104. pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
  3105. if (!pmgntframe)
  3106. return;
  3107. /* update attribute */
  3108. pattrib = &pmgntframe->attrib;
  3109. update_mgntframe_attrib23a(padapter, pattrib);
  3110. memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
  3111. mgmt = (struct ieee80211_mgmt *)(pmgntframe->buf_addr + TXDESC_OFFSET);
  3112. mgmt->frame_control =
  3113. cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
  3114. ether_addr_copy(mgmt->da, raddr);
  3115. ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
  3116. ether_addr_copy(mgmt->bssid, get_my_bssid23a(&pmlmeinfo->network));
  3117. mgmt->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(pmlmeext->mgnt_seq));
  3118. pmlmeext->mgnt_seq++;
  3119. mgmt->u.action.category = WLAN_CATEGORY_BACK;
  3120. pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr) + 1;
  3121. switch (action) {
  3122. case WLAN_ACTION_ADDBA_REQ:
  3123. pattrib->pktlen += sizeof(mgmt->u.action.u.addba_req);
  3124. mgmt->u.action.u.addba_req.action_code = action;
  3125. do {
  3126. pmlmeinfo->dialogToken++;
  3127. } while (pmlmeinfo->dialogToken == 0);
  3128. mgmt->u.action.u.addba_req.dialog_token =
  3129. pmlmeinfo->dialogToken;
  3130. if (rtl8723a_BT_coexist(padapter) &&
  3131. rtl8723a_BT_using_antenna_1(padapter) &&
  3132. (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
  3133. memcmp(raddr, tendaAPMac, 3))) {
  3134. /* A-MSDU NOT Supported */
  3135. BA_para_set = 0;
  3136. /* immediate Block Ack */
  3137. BA_para_set |= (1 << 1) &
  3138. IEEE80211_ADDBA_PARAM_POLICY_MASK;
  3139. /* TID */
  3140. BA_para_set |= (status << 2) &
  3141. IEEE80211_ADDBA_PARAM_TID_MASK;
  3142. /* max buffer size is 8 MSDU */
  3143. BA_para_set |= (8 << 6) &
  3144. IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
  3145. } else {
  3146. /* immediate ack & 64 buffer size */
  3147. BA_para_set = 0x1002 | ((status & 0xf) << 2);
  3148. }
  3149. put_unaligned_le16(BA_para_set,
  3150. &mgmt->u.action.u.addba_req.capab);
  3151. /* 5ms */
  3152. put_unaligned_le16(5000, &mgmt->u.action.u.addba_req.timeout);
  3153. psta = rtw_get_stainfo23a(pstapriv, raddr);
  3154. if (psta) {
  3155. int idx;
  3156. idx = status & 0x07;
  3157. start_seq =
  3158. (psta->sta_xmitpriv.txseq_tid[idx] & 0xfff) + 1;
  3159. DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
  3160. start_seq, idx);
  3161. psta->BA_starting_seqctrl[idx] = start_seq;
  3162. BA_starting_seqctrl = start_seq << 4;
  3163. } else
  3164. BA_starting_seqctrl = 0;
  3165. put_unaligned_le16(BA_starting_seqctrl,
  3166. &mgmt->u.action.u.addba_req.start_seq_num);
  3167. break;
  3168. case WLAN_ACTION_ADDBA_RESP:
  3169. pattrib->pktlen += sizeof(mgmt->u.action.u.addba_resp);
  3170. mgmt->u.action.u.addba_resp.action_code = action;
  3171. mgmt->u.action.u.addba_resp.dialog_token =
  3172. pmlmeinfo->ADDBA_req.dialog_token;
  3173. put_unaligned_le16(status,
  3174. &mgmt->u.action.u.addba_resp.status);
  3175. GetHalDefVar8192CUsb(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
  3176. &max_rx_ampdu_factor);
  3177. BA_para = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f;
  3178. if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
  3179. BA_para_set = BA_para | 0x1000; /* 64 buffer size */
  3180. else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
  3181. BA_para_set = BA_para | 0x0800; /* 32 buffer size */
  3182. else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
  3183. BA_para_set = BA_para | 0x0400; /* 16 buffer size */
  3184. else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
  3185. BA_para_set = BA_para | 0x0200; /* 8 buffer size */
  3186. else
  3187. BA_para_set = BA_para | 0x1000; /* 64 buffer size */
  3188. if (rtl8723a_BT_coexist(padapter) &&
  3189. rtl8723a_BT_using_antenna_1(padapter) &&
  3190. (pmlmeinfo->assoc_AP_vendor != broadcomAP ||
  3191. memcmp(raddr, tendaAPMac, 3))) {
  3192. /* max buffer size is 8 MSDU */
  3193. BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
  3194. BA_para_set |= (8 << 6) &
  3195. IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
  3196. }
  3197. if (pregpriv->ampdu_amsdu == 0)/* disabled */
  3198. BA_para_set &= ~BIT(0);
  3199. else if (pregpriv->ampdu_amsdu == 1)/* enabled */
  3200. BA_para_set |= BIT(0);
  3201. put_unaligned_le16(BA_para_set,
  3202. &mgmt->u.action.u.addba_resp.capab);
  3203. mgmt->u.action.u.addba_resp.timeout
  3204. = pmlmeinfo->ADDBA_req.BA_timeout_value;
  3205. pattrib->pktlen += 8;
  3206. break;
  3207. case WLAN_ACTION_DELBA:
  3208. pattrib->pktlen += sizeof(mgmt->u.action.u.delba);
  3209. mgmt->u.action.u.delba.action_code = action;
  3210. BA_para_set = (status & 0x1F) << 3;
  3211. mgmt->u.action.u.delba.params = cpu_to_le16(BA_para_set);
  3212. mgmt->u.action.u.delba.reason_code =
  3213. cpu_to_le16(WLAN_REASON_QSTA_NOT_USE);
  3214. pattrib->pktlen += 5;
  3215. break;
  3216. default:
  3217. break;
  3218. }
  3219. pattrib->last_txcmdsz = pattrib->pktlen;
  3220. dump_mgntframe23a(padapter, pmgntframe);
  3221. }
  3222. int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
  3223. {
  3224. struct sta_priv *pstapriv = &padapter->stapriv;
  3225. struct sta_info *psta = NULL;
  3226. /* struct recv_reorder_ctrl *preorder_ctrl; */
  3227. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3228. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3229. u16 tid;
  3230. if ((pmlmeinfo->state&0x03) != MSR_AP)
  3231. if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
  3232. return _SUCCESS;
  3233. psta = rtw_get_stainfo23a(pstapriv, addr);
  3234. if (psta == NULL)
  3235. return _SUCCESS;
  3236. if (initiator == 0) { /* recipient */
  3237. for (tid = 0; tid < MAXTID; tid++) {
  3238. if (psta->recvreorder_ctrl[tid].enable == true) {
  3239. DBG_8723A("rx agg disable tid(%d)\n", tid);
  3240. issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
  3241. psta->recvreorder_ctrl[tid].enable = false;
  3242. psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
  3243. }
  3244. }
  3245. } else if (initiator == 1) { /* originator */
  3246. for (tid = 0; tid < MAXTID; tid++) {
  3247. if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
  3248. DBG_8723A("tx agg disable tid(%d)\n", tid);
  3249. issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
  3250. psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
  3251. psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
  3252. }
  3253. }
  3254. }
  3255. return _SUCCESS;
  3256. }
  3257. int send_beacon23a(struct rtw_adapter *padapter)
  3258. {
  3259. bool bxmitok;
  3260. int issue = 0;
  3261. int poll = 0;
  3262. unsigned long start = jiffies;
  3263. unsigned int passing_time;
  3264. rtl8723a_bcn_valid(padapter);
  3265. do {
  3266. issue_beacon23a(padapter, 100);
  3267. issue++;
  3268. do {
  3269. yield();
  3270. bxmitok = rtl8723a_get_bcn_valid(padapter);
  3271. poll++;
  3272. } while ((poll % 10) != 0 && !bxmitok &&
  3273. !padapter->bSurpriseRemoved &&
  3274. !padapter->bDriverStopped);
  3275. } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
  3276. !padapter->bDriverStopped);
  3277. if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
  3278. return _FAIL;
  3279. passing_time = jiffies_to_msecs(jiffies - start);
  3280. if (!bxmitok) {
  3281. DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
  3282. return _FAIL;
  3283. } else {
  3284. if (passing_time > 100 || issue > 3)
  3285. DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
  3286. __func__, issue, poll, passing_time);
  3287. return _SUCCESS;
  3288. }
  3289. }
  3290. /****************************************************************************
  3291. Following are some utitity functions for WiFi MLME
  3292. *****************************************************************************/
  3293. bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
  3294. {
  3295. int i = 0;
  3296. u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
  3297. 60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
  3298. 114, 116, 118, 120, 122, 124, 126, 128, 130, 132,
  3299. 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
  3300. 161, 163, 165};
  3301. for (i = 0; i < sizeof(Channel_5G); i++)
  3302. if (channel == Channel_5G[i])
  3303. return true;
  3304. return false;
  3305. }
  3306. static void rtw_site_survey(struct rtw_adapter *padapter)
  3307. {
  3308. unsigned char survey_channel = 0;
  3309. enum rt_scan_type ScanType = SCAN_PASSIVE;
  3310. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3311. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3312. struct rtw_ieee80211_channel *ch;
  3313. if (pmlmeext->sitesurvey_res.channel_idx <
  3314. pmlmeext->sitesurvey_res.ch_num) {
  3315. ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
  3316. survey_channel = ch->hw_value;
  3317. ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ?
  3318. SCAN_PASSIVE : SCAN_ACTIVE;
  3319. }
  3320. if (survey_channel != 0) {
  3321. /* PAUSE 4-AC Queue when site_survey */
  3322. if (pmlmeext->sitesurvey_res.channel_idx == 0)
  3323. set_channel_bwmode23a(padapter, survey_channel,
  3324. HAL_PRIME_CHNL_OFFSET_DONT_CARE,
  3325. HT_CHANNEL_WIDTH_20);
  3326. else
  3327. SelectChannel23a(padapter, survey_channel);
  3328. if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
  3329. {
  3330. int i;
  3331. for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
  3332. if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
  3333. /* todo: to issue two probe req??? */
  3334. issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
  3335. /* msleep(SURVEY_TO>>1); */
  3336. issue_probereq(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
  3337. }
  3338. }
  3339. if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
  3340. /* todo: to issue two probe req??? */
  3341. issue_probereq(padapter, NULL, NULL);
  3342. /* msleep(SURVEY_TO>>1); */
  3343. issue_probereq(padapter, NULL, NULL);
  3344. }
  3345. }
  3346. set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
  3347. } else {
  3348. /* channel number is 0 or this channel is not valid. */
  3349. pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
  3350. /* switch back to the original channel */
  3351. set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
  3352. pmlmeext->cur_ch_offset,
  3353. pmlmeext->cur_bwmode);
  3354. /* flush 4-AC Queue after rtw_site_survey */
  3355. /* val8 = 0; */
  3356. /* config MSR */
  3357. rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
  3358. /* restore RX GAIN */
  3359. rtl8723a_set_initial_gain(padapter, 0xff);
  3360. /* turn on dynamic functions */
  3361. rtl8723a_odm_support_ability_restore(padapter);
  3362. if (is_client_associated_to_ap23a(padapter) == true)
  3363. issue_nulldata23a(padapter, NULL, 0, 3, 500);
  3364. rtl8723a_mlme_sitesurvey(padapter, 0);
  3365. report_surveydone_event23a(padapter);
  3366. pmlmeext->chan_scan_time = SURVEY_TO;
  3367. pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
  3368. }
  3369. }
  3370. /* collect bss info from Beacon and Probe request/response frames. */
  3371. static struct wlan_bssid_ex *collect_bss_info(struct rtw_adapter *padapter,
  3372. struct recv_frame *precv_frame)
  3373. {
  3374. struct sk_buff *skb = precv_frame->pkt;
  3375. struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
  3376. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  3377. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3378. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3379. struct wlan_bssid_ex *bssid;
  3380. const u8 *p;
  3381. u8 *pie;
  3382. unsigned int length;
  3383. int i;
  3384. length = skb->len;
  3385. bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
  3386. if (!bssid)
  3387. return NULL;
  3388. if (ieee80211_is_beacon(mgmt->frame_control)) {
  3389. length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
  3390. pie = mgmt->u.beacon.variable;
  3391. bssid->reserved = 1;
  3392. bssid->capability =
  3393. get_unaligned_le16(&mgmt->u.beacon.capab_info);
  3394. bssid->beacon_interval =
  3395. get_unaligned_le16(&mgmt->u.beacon.beacon_int);
  3396. bssid->tsf = get_unaligned_le64(&mgmt->u.beacon.timestamp);
  3397. } else if (ieee80211_is_probe_req(mgmt->frame_control)) {
  3398. length -= offsetof(struct ieee80211_mgmt, u.probe_req.variable);
  3399. pie = mgmt->u.probe_req.variable;
  3400. bssid->reserved = 2;
  3401. bssid->capability = 0;
  3402. bssid->beacon_interval =
  3403. padapter->registrypriv.dev_network.beacon_interval;
  3404. bssid->tsf = 0;
  3405. } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
  3406. length -=
  3407. offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
  3408. pie = mgmt->u.probe_resp.variable;
  3409. bssid->reserved = 3;
  3410. bssid->capability =
  3411. get_unaligned_le16(&mgmt->u.probe_resp.capab_info);
  3412. bssid->beacon_interval =
  3413. get_unaligned_le16(&mgmt->u.probe_resp.beacon_int);
  3414. bssid->tsf = get_unaligned_le64(&mgmt->u.probe_resp.timestamp);
  3415. } else {
  3416. length -= offsetof(struct ieee80211_mgmt, u.beacon.variable);
  3417. pie = mgmt->u.beacon.variable;
  3418. bssid->reserved = 0;
  3419. bssid->capability =
  3420. get_unaligned_le16(&mgmt->u.beacon.capab_info);
  3421. bssid->beacon_interval =
  3422. padapter->registrypriv.dev_network.beacon_interval;
  3423. bssid->tsf = 0;
  3424. }
  3425. if (length > MAX_IE_SZ) {
  3426. /* DBG_8723A("IE too long for survey event\n"); */
  3427. kfree(bssid);
  3428. return NULL;
  3429. }
  3430. bssid->Length = offsetof(struct wlan_bssid_ex, IEs) + length;
  3431. /* below is to copy the information element */
  3432. bssid->IELength = length;
  3433. memcpy(bssid->IEs, pie, bssid->IELength);
  3434. /* get the signal strength */
  3435. /* in dBM.raw data */
  3436. bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower;
  3437. bssid->SignalQuality =
  3438. precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
  3439. bssid->SignalStrength =
  3440. precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
  3441. /* checking SSID */
  3442. p = cfg80211_find_ie(WLAN_EID_SSID, bssid->IEs, bssid->IELength);
  3443. if (!p) {
  3444. DBG_8723A("marc: cannot find SSID for survey event\n");
  3445. goto fail;
  3446. }
  3447. if (p[1] > IEEE80211_MAX_SSID_LEN) {
  3448. DBG_8723A("%s()-%d: IE too long (%d) for survey "
  3449. "event\n", __func__, __LINE__, p[1]);
  3450. goto fail;
  3451. }
  3452. memcpy(bssid->Ssid.ssid, p + 2, p[1]);
  3453. bssid->Ssid.ssid_len = p[1];
  3454. /* checking rate info... */
  3455. i = 0;
  3456. p = cfg80211_find_ie(WLAN_EID_SUPP_RATES, bssid->IEs, bssid->IELength);
  3457. if (p) {
  3458. if (p[1] > NDIS_802_11_LENGTH_RATES_EX) {
  3459. DBG_8723A("%s()-%d: IE too long (%d) for survey "
  3460. "event\n", __func__, __LINE__, p[1]);
  3461. goto fail;
  3462. }
  3463. memcpy(bssid->SupportedRates, p + 2, p[1]);
  3464. i = p[1];
  3465. }
  3466. p = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, bssid->IEs,
  3467. bssid->IELength);
  3468. if (p) {
  3469. if (p[1] > (NDIS_802_11_LENGTH_RATES_EX-i)) {
  3470. DBG_8723A("%s()-%d: IE too long (%d) for survey "
  3471. "event\n", __func__, __LINE__, p[1]);
  3472. goto fail;
  3473. }
  3474. memcpy(bssid->SupportedRates + i, p + 2, p[1]);
  3475. }
  3476. /* Checking for DSConfig */
  3477. p = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bssid->IEs, bssid->IELength);
  3478. bssid->DSConfig = 0;
  3479. if (p) {
  3480. bssid->DSConfig = p[2];
  3481. } else {/* In 5G, some ap do not have DSSET IE */
  3482. /* checking HT info for channel */
  3483. p = cfg80211_find_ie(WLAN_EID_HT_OPERATION, bssid->IEs,
  3484. bssid->IELength);
  3485. if (p) {
  3486. struct ieee80211_ht_operation *HT_info =
  3487. (struct ieee80211_ht_operation *)(p + 2);
  3488. bssid->DSConfig = HT_info->primary_chan;
  3489. } else /* use current channel */
  3490. bssid->DSConfig = rtw_get_oper_ch23a(padapter);
  3491. }
  3492. if (ieee80211_is_probe_req(mgmt->frame_control)) {
  3493. /* FIXME */
  3494. bssid->ifmode = NL80211_IFTYPE_STATION;
  3495. ether_addr_copy(bssid->MacAddress, mgmt->sa);
  3496. bssid->Privacy = 1;
  3497. return bssid;
  3498. }
  3499. if (bssid->capability & WLAN_CAPABILITY_ESS) {
  3500. bssid->ifmode = NL80211_IFTYPE_STATION;
  3501. ether_addr_copy(bssid->MacAddress, mgmt->sa);
  3502. } else {
  3503. bssid->ifmode = NL80211_IFTYPE_ADHOC;
  3504. ether_addr_copy(bssid->MacAddress, mgmt->bssid);
  3505. }
  3506. if (bssid->capability & WLAN_CAPABILITY_PRIVACY)
  3507. bssid->Privacy = 1;
  3508. else
  3509. bssid->Privacy = 0;
  3510. bssid->ATIMWindow = 0;
  3511. /* 20/40 BSS Coexistence check */
  3512. if (pregistrypriv->wifi_spec == 1 &&
  3513. pmlmeinfo->bwmode_updated == false) {
  3514. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  3515. p = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, bssid->IEs,
  3516. bssid->IELength);
  3517. if (p && p[1] > 0) {
  3518. struct ieee80211_ht_cap *pHT_caps;
  3519. pHT_caps = (struct ieee80211_ht_cap *)(p + 2);
  3520. if (pHT_caps->cap_info &
  3521. cpu_to_le16(IEEE80211_HT_CAP_40MHZ_INTOLERANT))
  3522. pmlmepriv->num_FortyMHzIntolerant++;
  3523. } else
  3524. pmlmepriv->num_sta_no_ht++;
  3525. }
  3526. /* mark bss info receiving from nearby channel as SignalQuality 101 */
  3527. if (bssid->DSConfig != rtw_get_oper_ch23a(padapter))
  3528. bssid->SignalQuality = 101;
  3529. return bssid;
  3530. fail:
  3531. kfree (bssid);
  3532. return NULL;
  3533. }
  3534. static void start_create_ibss(struct rtw_adapter *padapter)
  3535. {
  3536. unsigned short caps;
  3537. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3538. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3539. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  3540. pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
  3541. pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
  3542. /* update wireless mode */
  3543. update_wireless_mode23a(padapter);
  3544. /* update capability */
  3545. caps = pnetwork->capability;
  3546. update_capinfo23a(padapter, caps);
  3547. if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc master */
  3548. rtl8723a_set_sec_cfg(padapter, 0xcf);
  3549. /* switch channel */
  3550. /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
  3551. set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
  3552. rtl8723a_SetBeaconRelatedRegisters(padapter);
  3553. /* set msr to MSR_ADHOC */
  3554. pmlmeinfo->state = MSR_ADHOC;
  3555. rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
  3556. /* issue beacon */
  3557. if (send_beacon23a(padapter) == _FAIL) {
  3558. RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
  3559. "issuing beacon frame fail....\n");
  3560. report_join_res23a(padapter, -1);
  3561. pmlmeinfo->state = MSR_NOLINK;
  3562. } else {
  3563. hw_var_set_bssid(padapter, padapter->registrypriv.dev_network.MacAddress);
  3564. hw_var_set_mlme_join(padapter, 0);
  3565. report_join_res23a(padapter, 1);
  3566. pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
  3567. }
  3568. } else {
  3569. DBG_8723A("%s: invalid cap:%x\n", __func__, caps);
  3570. return;
  3571. }
  3572. }
  3573. static void start_clnt_join(struct rtw_adapter *padapter)
  3574. {
  3575. unsigned short caps;
  3576. u8 val8;
  3577. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3578. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3579. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  3580. int beacon_timeout;
  3581. pmlmeext->cur_channel = (u8)pnetwork->DSConfig;
  3582. pmlmeinfo->bcn_interval = pnetwork->beacon_interval;
  3583. /* update wireless mode */
  3584. update_wireless_mode23a(padapter);
  3585. /* update capability */
  3586. caps = pnetwork->capability;
  3587. update_capinfo23a(padapter, caps);
  3588. if (caps & WLAN_CAPABILITY_ESS) {
  3589. /* switch channel */
  3590. set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
  3591. rtl8723a_set_media_status(padapter, MSR_INFRA);
  3592. val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ?
  3593. 0xcc: 0xcf;
  3594. rtl8723a_set_sec_cfg(padapter, val8);
  3595. /* switch channel */
  3596. /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
  3597. /* here wait for receiving the beacon to start auth */
  3598. /* and enable a timer */
  3599. beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
  3600. set_link_timer(pmlmeext, beacon_timeout);
  3601. mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
  3602. msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
  3603. pmlmeinfo->state = WIFI_FW_AUTH_NULL | MSR_INFRA;
  3604. } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */
  3605. rtl8723a_set_media_status(padapter, MSR_ADHOC);
  3606. rtl8723a_set_sec_cfg(padapter, 0xcf);
  3607. /* switch channel */
  3608. set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
  3609. rtl8723a_SetBeaconRelatedRegisters(padapter);
  3610. pmlmeinfo->state = MSR_ADHOC;
  3611. report_join_res23a(padapter, 1);
  3612. } else {
  3613. /* DBG_8723A("marc: invalid cap:%x\n", caps); */
  3614. return;
  3615. }
  3616. }
  3617. static void start_clnt_auth(struct rtw_adapter *padapter)
  3618. {
  3619. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3620. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3621. del_timer_sync(&pmlmeext->link_timer);
  3622. pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
  3623. pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
  3624. pmlmeinfo->auth_seq = 1;
  3625. pmlmeinfo->reauth_count = 0;
  3626. pmlmeinfo->reassoc_count = 0;
  3627. pmlmeinfo->link_count = 0;
  3628. pmlmeext->retry = 0;
  3629. /* Because of AP's not receiving deauth before */
  3630. /* AP may: 1)not response auth or 2)deauth us after link is complete */
  3631. /* issue deauth before issuing auth to deal with the situation */
  3632. /* Commented by Albert 2012/07/21 */
  3633. /* For the Win8 P2P connection, it will be hard to have a
  3634. successful connection if this Wi-Fi doesn't connect to it. */
  3635. issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress,
  3636. WLAN_REASON_DEAUTH_LEAVING);
  3637. DBG_8723A_LEVEL(_drv_always_, "start auth\n");
  3638. issue_auth(padapter, NULL, 0);
  3639. set_link_timer(pmlmeext, REAUTH_TO);
  3640. }
  3641. static void start_clnt_assoc(struct rtw_adapter *padapter)
  3642. {
  3643. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3644. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3645. del_timer_sync(&pmlmeext->link_timer);
  3646. pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
  3647. pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
  3648. issue_assocreq(padapter);
  3649. set_link_timer(pmlmeext, REASSOC_TO);
  3650. }
  3651. int receive_disconnect23a(struct rtw_adapter *padapter,
  3652. unsigned char *MacAddr, unsigned short reason)
  3653. {
  3654. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3655. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3656. /* check A3 */
  3657. if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
  3658. return _SUCCESS;
  3659. DBG_8723A("%s\n", __func__);
  3660. if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
  3661. if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
  3662. pmlmeinfo->state = MSR_NOLINK;
  3663. report_del_sta_event23a(padapter, MacAddr, reason);
  3664. } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
  3665. pmlmeinfo->state = MSR_NOLINK;
  3666. report_join_res23a(padapter, -2);
  3667. }
  3668. }
  3669. return _SUCCESS;
  3670. }
  3671. static void process_80211d(struct rtw_adapter *padapter,
  3672. struct wlan_bssid_ex *bssid)
  3673. {
  3674. struct registry_priv *pregistrypriv;
  3675. struct mlme_ext_priv *pmlmeext;
  3676. struct rt_channel_info *chplan_new;
  3677. u8 channel;
  3678. u8 i;
  3679. pregistrypriv = &padapter->registrypriv;
  3680. pmlmeext = &padapter->mlmeextpriv;
  3681. /* Adjust channel plan by AP Country IE */
  3682. if (pregistrypriv->enable80211d &&
  3683. !pmlmeext->update_channel_plan_by_ap_done) {
  3684. const u8 *ie, *p;
  3685. struct rt_channel_plan chplan_ap;
  3686. struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
  3687. u8 country[4];
  3688. u8 fcn; /* first channel number */
  3689. u8 noc; /* number of channel */
  3690. u8 j, k;
  3691. ie = cfg80211_find_ie(WLAN_EID_COUNTRY, bssid->IEs,
  3692. bssid->IELength);
  3693. if (!ie || ie[1] < IEEE80211_COUNTRY_IE_MIN_LEN)
  3694. return;
  3695. p = ie + 2;
  3696. ie += ie[1];
  3697. ie += 2;
  3698. memcpy(country, p, 3);
  3699. country[3] = '\0';
  3700. p += 3;
  3701. RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
  3702. "%s: 802.11d country =%s\n", __func__, country);
  3703. i = 0;
  3704. while ((ie - p) >= 3) {
  3705. fcn = *(p++);
  3706. noc = *(p++);
  3707. p++;
  3708. for (j = 0; j < noc; j++) {
  3709. if (fcn <= 14)
  3710. channel = fcn + j; /* 2.4 GHz */
  3711. else
  3712. channel = fcn + j * 4; /* 5 GHz */
  3713. chplan_ap.Channel[i++] = channel;
  3714. }
  3715. }
  3716. chplan_ap.Len = i;
  3717. memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
  3718. memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
  3719. chplan_new = pmlmeext->channel_set;
  3720. i = j = k = 0;
  3721. if (pregistrypriv->wireless_mode & WIRELESS_11G) {
  3722. do {
  3723. if (i == MAX_CHANNEL_NUM ||
  3724. chplan_sta[i].ChannelNum == 0 ||
  3725. chplan_sta[i].ChannelNum > 14)
  3726. break;
  3727. if (j == chplan_ap.Len ||
  3728. chplan_ap.Channel[j] > 14)
  3729. break;
  3730. if (chplan_sta[i].ChannelNum ==
  3731. chplan_ap.Channel[j]) {
  3732. chplan_new[k].ChannelNum =
  3733. chplan_ap.Channel[j];
  3734. chplan_new[k].ScanType = SCAN_ACTIVE;
  3735. i++;
  3736. j++;
  3737. k++;
  3738. } else if (chplan_sta[i].ChannelNum <
  3739. chplan_ap.Channel[j]) {
  3740. chplan_new[k].ChannelNum =
  3741. chplan_sta[i].ChannelNum;
  3742. chplan_new[k].ScanType =
  3743. SCAN_PASSIVE;
  3744. i++;
  3745. k++;
  3746. } else if (chplan_sta[i].ChannelNum >
  3747. chplan_ap.Channel[j]) {
  3748. chplan_new[k].ChannelNum =
  3749. chplan_ap.Channel[j];
  3750. chplan_new[k].ScanType =
  3751. SCAN_ACTIVE;
  3752. j++;
  3753. k++;
  3754. }
  3755. } while (1);
  3756. /* change AP not support channel to Passive scan */
  3757. while (i < MAX_CHANNEL_NUM &&
  3758. chplan_sta[i].ChannelNum != 0 &&
  3759. chplan_sta[i].ChannelNum <= 14) {
  3760. chplan_new[k].ChannelNum =
  3761. chplan_sta[i].ChannelNum;
  3762. chplan_new[k].ScanType = SCAN_PASSIVE;
  3763. i++;
  3764. k++;
  3765. }
  3766. /* add channel AP supported */
  3767. while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14){
  3768. chplan_new[k].ChannelNum = chplan_ap.Channel[j];
  3769. chplan_new[k].ScanType = SCAN_ACTIVE;
  3770. j++;
  3771. k++;
  3772. }
  3773. } else {
  3774. /* keep original STA 2.4G channel plan */
  3775. while (i < MAX_CHANNEL_NUM &&
  3776. chplan_sta[i].ChannelNum != 0 &&
  3777. chplan_sta[i].ChannelNum <= 14) {
  3778. chplan_new[k].ChannelNum =
  3779. chplan_sta[i].ChannelNum;
  3780. chplan_new[k].ScanType = chplan_sta[i].ScanType;
  3781. i++;
  3782. k++;
  3783. }
  3784. /* skip AP 2.4G channel plan */
  3785. while (j < chplan_ap.Len && chplan_ap.Channel[j] <= 14)
  3786. j++;
  3787. }
  3788. if (pregistrypriv->wireless_mode & WIRELESS_11A) {
  3789. do {
  3790. if (i == MAX_CHANNEL_NUM ||
  3791. chplan_sta[i].ChannelNum == 0)
  3792. break;
  3793. if (j == chplan_ap.Len ||
  3794. chplan_ap.Channel[j] == 0)
  3795. break;
  3796. if (chplan_sta[i].ChannelNum ==
  3797. chplan_ap.Channel[j]) {
  3798. chplan_new[k].ChannelNum =
  3799. chplan_ap.Channel[j];
  3800. chplan_new[k].ScanType = SCAN_ACTIVE;
  3801. i++;
  3802. j++;
  3803. k++;
  3804. } else if (chplan_sta[i].ChannelNum <
  3805. chplan_ap.Channel[j]) {
  3806. chplan_new[k].ChannelNum =
  3807. chplan_sta[i].ChannelNum;
  3808. chplan_new[k].ScanType = SCAN_PASSIVE;
  3809. i++;
  3810. k++;
  3811. } else if (chplan_sta[i].ChannelNum >
  3812. chplan_ap.Channel[j]) {
  3813. chplan_new[k].ChannelNum =
  3814. chplan_ap.Channel[j];
  3815. chplan_new[k].ScanType = SCAN_ACTIVE;
  3816. j++;
  3817. k++;
  3818. }
  3819. } while (1);
  3820. /* change AP not support channel to Passive scan */
  3821. while (i < MAX_CHANNEL_NUM &&
  3822. chplan_sta[i].ChannelNum != 0) {
  3823. chplan_new[k].ChannelNum =
  3824. chplan_sta[i].ChannelNum;
  3825. chplan_new[k].ScanType = SCAN_PASSIVE;
  3826. i++;
  3827. k++;
  3828. }
  3829. /* add channel AP supported */
  3830. while (j < chplan_ap.Len && chplan_ap.Channel[j] != 0) {
  3831. chplan_new[k].ChannelNum = chplan_ap.Channel[j];
  3832. chplan_new[k].ScanType = SCAN_ACTIVE;
  3833. j++;
  3834. k++;
  3835. }
  3836. } else {
  3837. /* keep original STA 5G channel plan */
  3838. while (i < MAX_CHANNEL_NUM &&
  3839. chplan_sta[i].ChannelNum != 0) {
  3840. chplan_new[k].ChannelNum =
  3841. chplan_sta[i].ChannelNum;
  3842. chplan_new[k].ScanType = chplan_sta[i].ScanType;
  3843. i++;
  3844. k++;
  3845. }
  3846. }
  3847. pmlmeext->update_channel_plan_by_ap_done = 1;
  3848. }
  3849. /* If channel is used by AP, set channel scan type to active */
  3850. channel = bssid->DSConfig;
  3851. chplan_new = pmlmeext->channel_set;
  3852. i = 0;
  3853. while (i < MAX_CHANNEL_NUM && chplan_new[i].ChannelNum != 0) {
  3854. if (chplan_new[i].ChannelNum == channel) {
  3855. if (chplan_new[i].ScanType == SCAN_PASSIVE) {
  3856. /* 5G Bnad 2, 3 (DFS) doesn't change
  3857. to active scan */
  3858. if (channel >= 52 && channel <= 144)
  3859. break;
  3860. chplan_new[i].ScanType = SCAN_ACTIVE;
  3861. RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
  3862. "%s: change channel %d scan type from passive to active\n",
  3863. __func__, channel);
  3864. }
  3865. break;
  3866. }
  3867. i++;
  3868. }
  3869. }
  3870. /****************************************************************************
  3871. Following are the functions to report events
  3872. *****************************************************************************/
  3873. void report_survey_event23a(struct rtw_adapter *padapter,
  3874. struct recv_frame *precv_frame)
  3875. {
  3876. struct cmd_obj *pcmd_obj;
  3877. u8 *pevtcmd;
  3878. u32 cmdsz;
  3879. struct survey_event *psurvey_evt;
  3880. struct C2HEvent_Header *pc2h_evt_hdr;
  3881. struct mlme_ext_priv *pmlmeext;
  3882. struct cmd_priv *pcmdpriv;
  3883. if (!padapter)
  3884. return;
  3885. pmlmeext = &padapter->mlmeextpriv;
  3886. pcmdpriv = &padapter->cmdpriv;
  3887. pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  3888. if (!pcmd_obj)
  3889. return;
  3890. cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
  3891. pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
  3892. if (!pevtcmd) {
  3893. kfree(pcmd_obj);
  3894. return;
  3895. }
  3896. pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
  3897. pcmd_obj->cmdsz = cmdsz;
  3898. pcmd_obj->parmbuf = pevtcmd;
  3899. pcmd_obj->rsp = NULL;
  3900. pcmd_obj->rspsz = 0;
  3901. pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
  3902. pc2h_evt_hdr->len = sizeof(struct survey_event);
  3903. pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
  3904. pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
  3905. psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
  3906. psurvey_evt->bss = collect_bss_info(padapter, precv_frame);
  3907. if (!psurvey_evt->bss) {
  3908. kfree(pcmd_obj);
  3909. kfree(pevtcmd);
  3910. return;
  3911. }
  3912. process_80211d(padapter, psurvey_evt->bss);
  3913. rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
  3914. pmlmeext->sitesurvey_res.bss_cnt++;
  3915. }
  3916. void report_surveydone_event23a(struct rtw_adapter *padapter)
  3917. {
  3918. struct cmd_obj *pcmd_obj;
  3919. u8 *pevtcmd;
  3920. u32 cmdsz;
  3921. struct surveydone_event *psurveydone_evt;
  3922. struct C2HEvent_Header *pc2h_evt_hdr;
  3923. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3924. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  3925. pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  3926. if (!pcmd_obj)
  3927. return;
  3928. cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
  3929. pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
  3930. if (!pevtcmd) {
  3931. kfree(pcmd_obj);
  3932. return;
  3933. }
  3934. pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
  3935. pcmd_obj->cmdsz = cmdsz;
  3936. pcmd_obj->parmbuf = pevtcmd;
  3937. pcmd_obj->rsp = NULL;
  3938. pcmd_obj->rspsz = 0;
  3939. pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
  3940. pc2h_evt_hdr->len = sizeof(struct surveydone_event);
  3941. pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
  3942. pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
  3943. psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
  3944. psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
  3945. DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
  3946. rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
  3947. }
  3948. void report_join_res23a(struct rtw_adapter *padapter, int res)
  3949. {
  3950. struct cmd_obj *pcmd_obj;
  3951. u8 *pevtcmd;
  3952. u32 cmdsz;
  3953. struct joinbss_event *pjoinbss_evt;
  3954. struct C2HEvent_Header *pc2h_evt_hdr;
  3955. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3956. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  3957. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  3958. pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  3959. if (!pcmd_obj)
  3960. return;
  3961. cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
  3962. pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
  3963. if (!pevtcmd) {
  3964. kfree(pcmd_obj);
  3965. return;
  3966. }
  3967. pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
  3968. pcmd_obj->cmdsz = cmdsz;
  3969. pcmd_obj->parmbuf = pevtcmd;
  3970. pcmd_obj->rsp = NULL;
  3971. pcmd_obj->rspsz = 0;
  3972. pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
  3973. pc2h_evt_hdr->len = sizeof(struct joinbss_event);
  3974. pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
  3975. pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
  3976. pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
  3977. memcpy((unsigned char *)&pjoinbss_evt->network.network,
  3978. &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
  3979. pjoinbss_evt->network.join_res = res;
  3980. DBG_8723A("report_join_res23a(%d)\n", res);
  3981. rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
  3982. rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
  3983. }
  3984. void report_del_sta_event23a(struct rtw_adapter *padapter,
  3985. unsigned char *MacAddr, unsigned short reason)
  3986. {
  3987. struct cmd_obj *pcmd_obj;
  3988. u8 *pevtcmd;
  3989. u32 cmdsz;
  3990. struct sta_info *psta;
  3991. int mac_id;
  3992. struct stadel_event *pdel_sta_evt;
  3993. struct C2HEvent_Header *pc2h_evt_hdr;
  3994. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  3995. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  3996. pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  3997. if (!pcmd_obj)
  3998. return;
  3999. cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
  4000. pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
  4001. if (!pevtcmd) {
  4002. kfree(pcmd_obj);
  4003. return;
  4004. }
  4005. pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
  4006. pcmd_obj->cmdsz = cmdsz;
  4007. pcmd_obj->parmbuf = pevtcmd;
  4008. pcmd_obj->rsp = NULL;
  4009. pcmd_obj->rspsz = 0;
  4010. pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
  4011. pc2h_evt_hdr->len = sizeof(struct stadel_event);
  4012. pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
  4013. pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
  4014. pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
  4015. ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
  4016. memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
  4017. 2);
  4018. psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
  4019. if (psta)
  4020. mac_id = (int)psta->mac_id;
  4021. else
  4022. mac_id = -1;
  4023. pdel_sta_evt->mac_id = mac_id;
  4024. DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
  4025. rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
  4026. }
  4027. void report_add_sta_event23a(struct rtw_adapter *padapter,
  4028. unsigned char *MacAddr, int cam_idx)
  4029. {
  4030. struct cmd_obj *pcmd_obj;
  4031. u8 *pevtcmd;
  4032. u32 cmdsz;
  4033. struct stassoc_event *padd_sta_evt;
  4034. struct C2HEvent_Header *pc2h_evt_hdr;
  4035. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4036. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  4037. pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  4038. if (!pcmd_obj)
  4039. return;
  4040. cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
  4041. pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
  4042. if (!pevtcmd) {
  4043. kfree(pcmd_obj);
  4044. return;
  4045. }
  4046. pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
  4047. pcmd_obj->cmdsz = cmdsz;
  4048. pcmd_obj->parmbuf = pevtcmd;
  4049. pcmd_obj->rsp = NULL;
  4050. pcmd_obj->rspsz = 0;
  4051. pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
  4052. pc2h_evt_hdr->len = sizeof(struct stassoc_event);
  4053. pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
  4054. pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
  4055. padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
  4056. ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
  4057. padd_sta_evt->cam_id = cam_idx;
  4058. DBG_8723A("report_add_sta_event23a: add STA\n");
  4059. rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
  4060. }
  4061. /****************************************************************************
  4062. Following are the event callback functions
  4063. *****************************************************************************/
  4064. /* for sta/adhoc mode */
  4065. void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
  4066. {
  4067. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  4068. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4069. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4070. /* ERP */
  4071. VCS_update23a(padapter, psta);
  4072. /* HT */
  4073. if (pmlmepriv->htpriv.ht_option) {
  4074. psta->htpriv.ht_option = true;
  4075. psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
  4076. if (support_short_GI23a(padapter, &pmlmeinfo->ht_cap))
  4077. psta->htpriv.sgi = true;
  4078. psta->qos_option = true;
  4079. } else {
  4080. psta->htpriv.ht_option = false;
  4081. psta->htpriv.ampdu_enable = false;
  4082. psta->htpriv.sgi = false;
  4083. psta->qos_option = false;
  4084. }
  4085. psta->htpriv.bwmode = pmlmeext->cur_bwmode;
  4086. psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
  4087. psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
  4088. psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
  4089. /* QoS */
  4090. if (pmlmepriv->qos_option)
  4091. psta->qos_option = true;
  4092. psta->state = _FW_LINKED;
  4093. }
  4094. void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter,
  4095. int join_res)
  4096. {
  4097. struct sta_info *psta, *psta_bmc;
  4098. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4099. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4100. struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
  4101. struct sta_priv *pstapriv = &padapter->stapriv;
  4102. if (join_res < 0) {
  4103. hw_var_set_mlme_join(padapter, 1);
  4104. hw_var_set_bssid(padapter, null_addr);
  4105. /* restore to initial setting. */
  4106. update_tx_basic_rate23a(padapter,
  4107. padapter->registrypriv.wireless_mode);
  4108. goto exit_mlmeext_joinbss_event_callback23a;
  4109. }
  4110. if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
  4111. /* for bc/mc */
  4112. psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
  4113. if (psta_bmc) {
  4114. pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
  4115. update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
  4116. Update_RA_Entry23a(padapter, psta_bmc);
  4117. }
  4118. }
  4119. /* turn on dynamic functions */
  4120. rtl8723a_odm_support_ability_set(padapter, DYNAMIC_ALL_FUNC_ENABLE);
  4121. /* update IOT-releated issue */
  4122. update_IOT_info23a(padapter);
  4123. HalSetBrateCfg23a(padapter, cur_network->SupportedRates);
  4124. /* BCN interval */
  4125. rtl8723a_set_beacon_interval(padapter, pmlmeinfo->bcn_interval);
  4126. /* update capability */
  4127. update_capinfo23a(padapter, pmlmeinfo->capability);
  4128. /* WMM, Update EDCA param */
  4129. WMMOnAssocRsp23a(padapter);
  4130. /* HT */
  4131. HTOnAssocRsp23a(padapter);
  4132. /* Set cur_channel&cur_bwmode&cur_ch_offset */
  4133. set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
  4134. psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
  4135. if (psta) { /* only for infra. mode */
  4136. pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
  4137. /* DBG_8723A("set_sta_rate23a\n"); */
  4138. psta->wireless_mode = pmlmeext->cur_wireless_mode;
  4139. /* set per sta rate after updating HT cap. */
  4140. set_sta_rate23a(padapter, psta);
  4141. }
  4142. hw_var_set_mlme_join(padapter, 2);
  4143. if ((pmlmeinfo->state&0x03) == MSR_INFRA) {
  4144. /* correcting TSF */
  4145. rtw_correct_TSF(padapter);
  4146. /* set_link_timer(pmlmeext, DISCONNECT_TO); */
  4147. }
  4148. rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
  4149. exit_mlmeext_joinbss_event_callback23a:
  4150. DBG_8723A("=>%s\n", __func__);
  4151. }
  4152. void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter,
  4153. struct sta_info *psta)
  4154. {
  4155. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4156. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4157. DBG_8723A("%s\n", __func__);
  4158. if ((pmlmeinfo->state & 0x03) == MSR_ADHOC) {
  4159. /* adhoc master or sta_count>1 */
  4160. if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
  4161. /* nothing to do */
  4162. } else { /* adhoc client */
  4163. /* correcting TSF */
  4164. rtw_correct_TSF(padapter);
  4165. /* start beacon */
  4166. if (send_beacon23a(padapter) != _SUCCESS) {
  4167. pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
  4168. pmlmeinfo->state ^= MSR_ADHOC;
  4169. return;
  4170. }
  4171. pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
  4172. }
  4173. hw_var_set_mlme_join(padapter, 2);
  4174. }
  4175. pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
  4176. /* rate radaptive */
  4177. Update_RA_Entry23a(padapter, psta);
  4178. /* update adhoc sta_info */
  4179. update_sta_info23a(padapter, psta);
  4180. }
  4181. void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
  4182. {
  4183. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4184. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4185. if (is_client_associated_to_ap23a(padapter) ||
  4186. is_IBSS_empty23a(padapter)) {
  4187. /* set_opmode_cmd(padapter, infra_client_with_mlme); */
  4188. hw_var_set_mlme_disconnect(padapter);
  4189. hw_var_set_bssid(padapter, null_addr);
  4190. /* restore to initial setting. */
  4191. update_tx_basic_rate23a(padapter,
  4192. padapter->registrypriv.wireless_mode);
  4193. /* switch to the 20M Hz mode after disconnect */
  4194. pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
  4195. pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  4196. set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
  4197. pmlmeext->cur_ch_offset,
  4198. pmlmeext->cur_bwmode);
  4199. flush_all_cam_entry23a(padapter);
  4200. pmlmeinfo->state = MSR_NOLINK;
  4201. /* set MSR to no link state -> infra. mode */
  4202. rtl8723a_set_media_status(padapter, MSR_INFRA);
  4203. del_timer_sync(&pmlmeext->link_timer);
  4204. }
  4205. }
  4206. static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
  4207. {
  4208. u8 ret = false;
  4209. if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) &&
  4210. sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
  4211. sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
  4212. ret = false;
  4213. else
  4214. ret = true;
  4215. sta_update_last_rx_pkts(psta);
  4216. return ret;
  4217. }
  4218. void linked_status_chk23a(struct rtw_adapter *padapter)
  4219. {
  4220. u32 i;
  4221. struct sta_info *psta;
  4222. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  4223. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4224. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4225. struct sta_priv *pstapriv = &padapter->stapriv;
  4226. if (is_client_associated_to_ap23a(padapter)) {
  4227. /* linked infrastructure client mode */
  4228. int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
  4229. int rx_chk_limit;
  4230. rx_chk_limit = 4;
  4231. psta = rtw_get_stainfo23a(pstapriv,
  4232. pmlmeinfo->network.MacAddress);
  4233. if (psta) {
  4234. bool is_p2p_enable = false;
  4235. if (chk_ap_is_alive(padapter, psta) == false)
  4236. rx_chk = _FAIL;
  4237. if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
  4238. tx_chk = _FAIL;
  4239. if (pmlmeext->active_keep_alive_check &&
  4240. (rx_chk == _FAIL || tx_chk == _FAIL)) {
  4241. u8 backup_oper_channel = 0;
  4242. /* switch to correct channel of current
  4243. network before issue keep-alive frames */
  4244. if (rtw_get_oper_ch23a(padapter) !=
  4245. pmlmeext->cur_channel) {
  4246. backup_oper_channel =
  4247. rtw_get_oper_ch23a(padapter);
  4248. SelectChannel23a(padapter,
  4249. pmlmeext->cur_channel);
  4250. }
  4251. if (rx_chk != _SUCCESS)
  4252. issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
  4253. if ((tx_chk != _SUCCESS &&
  4254. pmlmeinfo->link_count++ == 0xf) ||
  4255. rx_chk != _SUCCESS) {
  4256. tx_chk = issue_nulldata23a(padapter,
  4257. psta->hwaddr,
  4258. 0, 3, 1);
  4259. /* if tx acked and p2p disabled,
  4260. set rx_chk _SUCCESS to reset retry
  4261. count */
  4262. if (tx_chk == _SUCCESS &&
  4263. !is_p2p_enable)
  4264. rx_chk = _SUCCESS;
  4265. }
  4266. /* back to the original operation channel */
  4267. if (backup_oper_channel>0)
  4268. SelectChannel23a(padapter,
  4269. backup_oper_channel);
  4270. } else {
  4271. if (rx_chk != _SUCCESS) {
  4272. if (pmlmeext->retry == 0) {
  4273. issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
  4274. issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
  4275. issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
  4276. }
  4277. }
  4278. if (tx_chk != _SUCCESS &&
  4279. pmlmeinfo->link_count++ == 0xf)
  4280. tx_chk = issue_nulldata23a(padapter,
  4281. NULL, 0, 1,
  4282. 0);
  4283. }
  4284. if (rx_chk == _FAIL) {
  4285. pmlmeext->retry++;
  4286. if (pmlmeext->retry > rx_chk_limit) {
  4287. DBG_8723A_LEVEL(_drv_always_,
  4288. "%s(%s): disconnect or "
  4289. "roaming\n", __func__,
  4290. padapter->pnetdev->name);
  4291. receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
  4292. WLAN_REASON_EXPIRATION_CHK);
  4293. return;
  4294. }
  4295. } else
  4296. pmlmeext->retry = 0;
  4297. if (tx_chk == _FAIL)
  4298. pmlmeinfo->link_count &= 0xf;
  4299. else {
  4300. pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
  4301. pmlmeinfo->link_count = 0;
  4302. }
  4303. }
  4304. } else if (is_client_associated_to_ibss23a(padapter)) {
  4305. /* linked IBSS mode */
  4306. /* for each assoc list entry to check the rx pkt counter */
  4307. for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
  4308. if (pmlmeinfo->FW_sta_info[i].status == 1) {
  4309. psta = pmlmeinfo->FW_sta_info[i].psta;
  4310. if (!psta)
  4311. continue;
  4312. if (pmlmeinfo->FW_sta_info[i].rx_pkt ==
  4313. sta_rx_pkts(psta)) {
  4314. if (pmlmeinfo->FW_sta_info[i].retry<3) {
  4315. pmlmeinfo->FW_sta_info[i].retry++;
  4316. } else {
  4317. pmlmeinfo->FW_sta_info[i].retry = 0;
  4318. pmlmeinfo->FW_sta_info[i].status = 0;
  4319. report_del_sta_event23a(padapter, psta->hwaddr,
  4320. 65535/* indicate disconnect caused by no rx */
  4321. );
  4322. }
  4323. } else {
  4324. pmlmeinfo->FW_sta_info[i].retry = 0;
  4325. pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
  4326. }
  4327. }
  4328. }
  4329. /* set_link_timer(pmlmeext, DISCONNECT_TO); */
  4330. }
  4331. }
  4332. static void survey_timer_hdl(unsigned long data)
  4333. {
  4334. struct rtw_adapter *padapter = (struct rtw_adapter *)data;
  4335. struct cmd_obj *ph2c;
  4336. struct sitesurvey_parm *psurveyPara;
  4337. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  4338. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4339. /* issue rtw_sitesurvey_cmd23a */
  4340. if (pmlmeext->sitesurvey_res.state > SCAN_START) {
  4341. if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
  4342. pmlmeext->sitesurvey_res.channel_idx++;
  4343. if (pmlmeext->scan_abort == true) {
  4344. pmlmeext->sitesurvey_res.channel_idx =
  4345. pmlmeext->sitesurvey_res.ch_num;
  4346. DBG_8723A("%s idx:%d\n", __func__,
  4347. pmlmeext->sitesurvey_res.channel_idx);
  4348. pmlmeext->scan_abort = false;/* reset */
  4349. }
  4350. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  4351. if (!ph2c)
  4352. goto exit_survey_timer_hdl;
  4353. psurveyPara = kzalloc(sizeof(struct sitesurvey_parm),
  4354. GFP_ATOMIC);
  4355. if (!psurveyPara) {
  4356. kfree(ph2c);
  4357. goto exit_survey_timer_hdl;
  4358. }
  4359. init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
  4360. GEN_CMD_CODE(_SiteSurvey));
  4361. rtw_enqueue_cmd23a(pcmdpriv, ph2c);
  4362. }
  4363. exit_survey_timer_hdl:
  4364. return;
  4365. }
  4366. static void link_timer_hdl(unsigned long data)
  4367. {
  4368. struct rtw_adapter *padapter = (struct rtw_adapter *)data;
  4369. /* static unsigned int rx_pkt = 0; */
  4370. /* static u64 tx_cnt = 0; */
  4371. /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
  4372. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4373. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4374. /* struct sta_priv *pstapriv = &padapter->stapriv; */
  4375. if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
  4376. DBG_8723A("link_timer_hdl:no beacon while connecting\n");
  4377. pmlmeinfo->state = MSR_NOLINK;
  4378. report_join_res23a(padapter, -3);
  4379. } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
  4380. /* re-auth timer */
  4381. if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
  4382. /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
  4383. /* */
  4384. pmlmeinfo->state = 0;
  4385. report_join_res23a(padapter, -1);
  4386. return;
  4387. /* */
  4388. /* else */
  4389. /* */
  4390. /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
  4391. /* pmlmeinfo->reauth_count = 0; */
  4392. /* */
  4393. }
  4394. DBG_8723A("link_timer_hdl: auth timeout and try again\n");
  4395. pmlmeinfo->auth_seq = 1;
  4396. issue_auth(padapter, NULL, 0);
  4397. set_link_timer(pmlmeext, REAUTH_TO);
  4398. } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
  4399. /* re-assoc timer */
  4400. if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
  4401. pmlmeinfo->state = MSR_NOLINK;
  4402. report_join_res23a(padapter, -2);
  4403. return;
  4404. }
  4405. DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
  4406. issue_assocreq(padapter);
  4407. set_link_timer(pmlmeext, REASSOC_TO);
  4408. }
  4409. }
  4410. static void addba_timer_hdl(unsigned long data)
  4411. {
  4412. struct sta_info *psta = (struct sta_info *)data;
  4413. struct ht_priv *phtpriv;
  4414. if (!psta)
  4415. return;
  4416. phtpriv = &psta->htpriv;
  4417. if (phtpriv->ht_option && phtpriv->ampdu_enable) {
  4418. if (phtpriv->candidate_tid_bitmap)
  4419. phtpriv->candidate_tid_bitmap = 0x0;
  4420. }
  4421. }
  4422. void init_addba_retry_timer23a(struct sta_info *psta)
  4423. {
  4424. setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
  4425. (unsigned long)psta);
  4426. }
  4427. void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
  4428. {
  4429. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4430. setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
  4431. (unsigned long)padapter);
  4432. setup_timer(&pmlmeext->link_timer, link_timer_hdl,
  4433. (unsigned long)padapter);
  4434. }
  4435. int NULL_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4436. {
  4437. return H2C_SUCCESS;
  4438. }
  4439. int setopmode_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4440. {
  4441. enum nl80211_iftype type;
  4442. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4443. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4444. const struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
  4445. switch (psetop->mode) {
  4446. case NL80211_IFTYPE_P2P_GO:
  4447. case NL80211_IFTYPE_AP:
  4448. pmlmeinfo->state = MSR_AP;
  4449. type = MSR_AP;
  4450. break;
  4451. case NL80211_IFTYPE_P2P_CLIENT:
  4452. case NL80211_IFTYPE_STATION:
  4453. /* clear state */
  4454. pmlmeinfo->state &= ~(BIT(0)|BIT(1));
  4455. /* set to STATION_STATE */
  4456. pmlmeinfo->state |= MSR_INFRA;
  4457. type = MSR_INFRA;
  4458. break;
  4459. case NL80211_IFTYPE_ADHOC:
  4460. type = MSR_ADHOC;
  4461. break;
  4462. default:
  4463. type = MSR_NOLINK;
  4464. break;
  4465. }
  4466. hw_var_set_opmode(padapter, type);
  4467. /* Set_NETYPE0_MSR(padapter, type); */
  4468. return H2C_SUCCESS;
  4469. }
  4470. int createbss_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4471. {
  4472. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4473. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4474. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  4475. const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
  4476. /* u32 initialgain; */
  4477. if (pparm->ifmode == NL80211_IFTYPE_AP ||
  4478. pparm->ifmode == NL80211_IFTYPE_P2P_GO) {
  4479. #ifdef CONFIG_8723AU_AP_MODE
  4480. if (pmlmeinfo->state == MSR_AP) {
  4481. /* todo: */
  4482. return H2C_SUCCESS;
  4483. }
  4484. #endif
  4485. }
  4486. /* below is for ad-hoc master */
  4487. if (pparm->ifmode == NL80211_IFTYPE_ADHOC) {
  4488. rtw_joinbss_reset23a(padapter);
  4489. pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
  4490. pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  4491. pmlmeinfo->ERP_enable = 0;
  4492. pmlmeinfo->WMM_enable = 0;
  4493. pmlmeinfo->HT_enable = 0;
  4494. pmlmeinfo->HT_caps_enable = 0;
  4495. pmlmeinfo->HT_info_enable = 0;
  4496. /* disable dynamic functions, such as high power, DIG */
  4497. rtl8723a_odm_support_ability_backup(padapter);
  4498. rtl8723a_odm_support_ability_clr(padapter,
  4499. DYNAMIC_FUNC_DISABLE);
  4500. /* cancel link timer */
  4501. del_timer_sync(&pmlmeext->link_timer);
  4502. /* clear CAM */
  4503. flush_all_cam_entry23a(padapter);
  4504. if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
  4505. return H2C_PARAMETERS_ERROR;
  4506. memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
  4507. start_create_ibss(padapter);
  4508. }
  4509. return H2C_SUCCESS;
  4510. }
  4511. int join_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4512. {
  4513. struct registry_priv *pregpriv = &padapter->registrypriv;
  4514. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4515. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4516. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  4517. const struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
  4518. struct ieee80211_ht_operation *pht_info;
  4519. u32 i;
  4520. u8 *p;
  4521. /* u32 initialgain; */
  4522. /* u32 acparm; */
  4523. /* check already connecting to AP or not */
  4524. if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
  4525. if (pmlmeinfo->state & MSR_INFRA)
  4526. issue_deauth_ex(padapter, pnetwork->MacAddress,
  4527. WLAN_REASON_DEAUTH_LEAVING, 5, 100);
  4528. pmlmeinfo->state = MSR_NOLINK;
  4529. /* clear CAM */
  4530. flush_all_cam_entry23a(padapter);
  4531. del_timer_sync(&pmlmeext->link_timer);
  4532. /* set MSR to nolink -> infra. mode */
  4533. rtl8723a_set_media_status(padapter, MSR_INFRA);
  4534. hw_var_set_mlme_disconnect(padapter);
  4535. }
  4536. rtw_joinbss_reset23a(padapter);
  4537. pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
  4538. pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  4539. pmlmeinfo->ERP_enable = 0;
  4540. pmlmeinfo->WMM_enable = 0;
  4541. pmlmeinfo->HT_enable = 0;
  4542. pmlmeinfo->HT_caps_enable = 0;
  4543. pmlmeinfo->HT_info_enable = 0;
  4544. pmlmeinfo->bwmode_updated = false;
  4545. /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
  4546. if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
  4547. return H2C_PARAMETERS_ERROR;
  4548. memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
  4549. /* Check AP vendor to move rtw_joinbss_cmd23a() */
  4550. /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
  4551. pnetwork->IELength); */
  4552. for (i = 0; i < pnetwork->IELength;) {
  4553. p = pnetwork->IEs + i;
  4554. switch (p[0]) {
  4555. case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
  4556. if (!memcmp(p + 2, WMM_OUI23A, 4))
  4557. pmlmeinfo->WMM_enable = 1;
  4558. break;
  4559. case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */
  4560. pmlmeinfo->HT_caps_enable = 1;
  4561. break;
  4562. case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */
  4563. pmlmeinfo->HT_info_enable = 1;
  4564. /* spec case only for cisco's ap because cisco's ap
  4565. * issue assoc rsp using mcs rate @40MHz or @20MHz */
  4566. pht_info = (struct ieee80211_ht_operation *)(p + 2);
  4567. if (pregpriv->cbw40_enable &&
  4568. (pht_info->ht_param &
  4569. IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
  4570. /* switch to the 40M Hz mode according to AP */
  4571. pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
  4572. switch (pht_info->ht_param &
  4573. IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
  4574. case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
  4575. pmlmeext->cur_ch_offset =
  4576. HAL_PRIME_CHNL_OFFSET_LOWER;
  4577. break;
  4578. case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
  4579. pmlmeext->cur_ch_offset =
  4580. HAL_PRIME_CHNL_OFFSET_UPPER;
  4581. break;
  4582. default:
  4583. pmlmeext->cur_ch_offset =
  4584. HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  4585. break;
  4586. }
  4587. DBG_8723A("set ch/bw before connected\n");
  4588. }
  4589. break;
  4590. default:
  4591. break;
  4592. }
  4593. i += (p[1] + 2);
  4594. }
  4595. hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
  4596. hw_var_set_mlme_join(padapter, 0);
  4597. /* cancel link timer */
  4598. del_timer_sync(&pmlmeext->link_timer);
  4599. start_clnt_join(padapter);
  4600. return H2C_SUCCESS;
  4601. }
  4602. int disconnect_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4603. {
  4604. const struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
  4605. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4606. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4607. struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
  4608. if (is_client_associated_to_ap23a(padapter)) {
  4609. issue_deauth_ex(padapter, pnetwork->MacAddress,
  4610. WLAN_REASON_DEAUTH_LEAVING,
  4611. param->deauth_timeout_ms/100, 100);
  4612. }
  4613. /* set_opmode_cmd(padapter, infra_client_with_mlme); */
  4614. /* pmlmeinfo->state = MSR_NOLINK; */
  4615. hw_var_set_mlme_disconnect(padapter);
  4616. hw_var_set_bssid(padapter, null_addr);
  4617. /* restore to initial setting. */
  4618. update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
  4619. if ((pmlmeinfo->state & 0x03) == MSR_ADHOC ||
  4620. (pmlmeinfo->state & 0x03) == MSR_AP)
  4621. rtl8723a_set_bcn_func(padapter, 0); /* Stop BCN */
  4622. /* set MSR to no link state -> infra. mode */
  4623. rtl8723a_set_media_status(padapter, MSR_INFRA);
  4624. pmlmeinfo->state = MSR_NOLINK;
  4625. /* switch to the 20M Hz mode after disconnect */
  4626. pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
  4627. pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  4628. set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
  4629. pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
  4630. flush_all_cam_entry23a(padapter);
  4631. del_timer_sync(&pmlmeext->link_timer);
  4632. rtw_free_uc_swdec_pending_queue23a(padapter);
  4633. return H2C_SUCCESS;
  4634. }
  4635. static int
  4636. rtw_scan_ch_decision(struct rtw_adapter *padapter,
  4637. struct rtw_ieee80211_channel *out, u32 out_num,
  4638. const struct rtw_ieee80211_channel *in, u32 in_num)
  4639. {
  4640. int i, j;
  4641. int scan_ch_num = 0;
  4642. int set_idx;
  4643. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4644. /* clear out first */
  4645. memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
  4646. /* acquire channels from in */
  4647. j = 0;
  4648. for (i = 0;i<in_num;i++) {
  4649. if (in[i].hw_value &&
  4650. !(in[i].flags & IEEE80211_CHAN_DISABLED) &&
  4651. (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set,
  4652. in[i].hw_value)) >= 0) {
  4653. memcpy(&out[j], &in[i],
  4654. sizeof(struct rtw_ieee80211_channel));
  4655. if (pmlmeext->channel_set[set_idx].ScanType ==
  4656. SCAN_PASSIVE)
  4657. out[j].flags &= IEEE80211_CHAN_NO_IR;
  4658. j++;
  4659. }
  4660. if (j>= out_num)
  4661. break;
  4662. }
  4663. /* if out is empty, use channel_set as default */
  4664. if (j == 0) {
  4665. for (i = 0;i<pmlmeext->max_chan_nums;i++) {
  4666. out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
  4667. if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
  4668. out[i].flags &= IEEE80211_CHAN_NO_IR;
  4669. j++;
  4670. }
  4671. }
  4672. if (padapter->setband == GHZ_24) { /* 2.4G */
  4673. for (i = 0; i < j ; i++) {
  4674. if (out[i].hw_value > 35)
  4675. memset(&out[i], 0,
  4676. sizeof(struct rtw_ieee80211_channel));
  4677. else
  4678. scan_ch_num++;
  4679. }
  4680. j = scan_ch_num;
  4681. } else if (padapter->setband == GHZ_50) { /* 5G */
  4682. for (i = 0; i < j ; i++) {
  4683. if (out[i].hw_value > 35) {
  4684. memcpy(&out[scan_ch_num++], &out[i],
  4685. sizeof(struct rtw_ieee80211_channel));
  4686. }
  4687. }
  4688. j = scan_ch_num;
  4689. } else
  4690. {}
  4691. return j;
  4692. }
  4693. int sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4694. {
  4695. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4696. const struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
  4697. u8 bdelayscan = false;
  4698. u32 initialgain;
  4699. u32 i;
  4700. if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
  4701. pmlmeext->sitesurvey_res.state = SCAN_START;
  4702. pmlmeext->sitesurvey_res.bss_cnt = 0;
  4703. pmlmeext->sitesurvey_res.channel_idx = 0;
  4704. for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
  4705. if (pparm->ssid[i].ssid_len) {
  4706. memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
  4707. pparm->ssid[i].ssid,
  4708. IEEE80211_MAX_SSID_LEN);
  4709. pmlmeext->sitesurvey_res.ssid[i].ssid_len =
  4710. pparm->ssid[i].ssid_len;
  4711. } else {
  4712. pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
  4713. }
  4714. }
  4715. pmlmeext->sitesurvey_res.ch_num =
  4716. rtw_scan_ch_decision(padapter,
  4717. pmlmeext->sitesurvey_res.ch,
  4718. RTW_CHANNEL_SCAN_AMOUNT,
  4719. pparm->ch, pparm->ch_num);
  4720. pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
  4721. /* issue null data if associating to the AP */
  4722. if (is_client_associated_to_ap23a(padapter)) {
  4723. pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
  4724. /* switch to correct channel of current network
  4725. before issue keep-alive frames */
  4726. if (rtw_get_oper_ch23a(padapter) !=
  4727. pmlmeext->cur_channel)
  4728. SelectChannel23a(padapter,
  4729. pmlmeext->cur_channel);
  4730. issue_nulldata23a(padapter, NULL, 1, 3, 500);
  4731. bdelayscan = true;
  4732. }
  4733. if (bdelayscan) {
  4734. /* delay 50ms to protect nulldata(1). */
  4735. set_survey_timer(pmlmeext, 50);
  4736. return H2C_SUCCESS;
  4737. }
  4738. }
  4739. if (pmlmeext->sitesurvey_res.state == SCAN_START ||
  4740. pmlmeext->sitesurvey_res.state == SCAN_TXNULL) {
  4741. /* disable dynamic functions, such as high power, DIG */
  4742. rtl8723a_odm_support_ability_backup(padapter);
  4743. rtl8723a_odm_support_ability_clr(padapter,
  4744. DYNAMIC_FUNC_DISABLE);
  4745. /* config the initial gain under scanning, need to
  4746. write the BB registers */
  4747. if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == true)
  4748. initialgain = 0x30;
  4749. else
  4750. initialgain = 0x1E;
  4751. rtl8723a_set_initial_gain(padapter, initialgain);
  4752. /* set MSR to no link state */
  4753. rtl8723a_set_media_status(padapter, MSR_NOLINK);
  4754. rtl8723a_mlme_sitesurvey(padapter, 1);
  4755. pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
  4756. }
  4757. rtw_site_survey(padapter);
  4758. return H2C_SUCCESS;
  4759. }
  4760. int setauth_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4761. {
  4762. const struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
  4763. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4764. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4765. if (pparm->mode < 4)
  4766. pmlmeinfo->auth_algo = pparm->mode;
  4767. return H2C_SUCCESS;
  4768. }
  4769. int setkey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4770. {
  4771. unsigned short ctrl;
  4772. const struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
  4773. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4774. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4775. unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  4776. /* main tx key for wep. */
  4777. if (pparm->set_tx)
  4778. pmlmeinfo->key_index = pparm->keyid;
  4779. /* write cam */
  4780. ctrl = BIT(15) | (pparm->algorithm) << 2 | pparm->keyid;
  4781. DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 "
  4782. "WEP104-5 TKIP-2 AES-4) keyid:%d\n",
  4783. pparm->algorithm, pparm->keyid);
  4784. rtl8723a_cam_write(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
  4785. /* allow multicast packets to driver */
  4786. rtl8723a_on_rcr_am(padapter);
  4787. return H2C_SUCCESS;
  4788. }
  4789. int set_stakey_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4790. {
  4791. u16 ctrl = 0;
  4792. u8 cam_id;/* cam_entry */
  4793. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4794. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4795. const struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
  4796. /* cam_entry: */
  4797. /* 0~3 for default key */
  4798. /* for concurrent mode (ap+sta): */
  4799. /* default key is disable, using sw encrypt/decrypt */
  4800. /* cam_entry = 4 for sta mode (macid = 0) */
  4801. /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
  4802. /* for concurrent mode (sta+sta): */
  4803. /* default key is disable, using sw encrypt/decrypt */
  4804. /* cam_entry = 4 mapping to macid = 0 */
  4805. /* cam_entry = 5 mapping to macid = 2 */
  4806. cam_id = 4;
  4807. DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 "
  4808. "WEP104-5 TKIP-2 AES-4) camid:%d\n",
  4809. pparm->algorithm, cam_id);
  4810. if ((pmlmeinfo->state & 0x03) == MSR_AP) {
  4811. struct sta_info *psta;
  4812. struct sta_priv *pstapriv = &padapter->stapriv;
  4813. if (pparm->algorithm == 0) { /* clear cam entry */
  4814. clear_cam_entry23a(padapter, pparm->id);
  4815. return H2C_SUCCESS_RSP;
  4816. }
  4817. psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
  4818. if (psta) {
  4819. ctrl = BIT(15) | (pparm->algorithm << 2);
  4820. DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm "
  4821. "=%d\n", pparm->algorithm);
  4822. if (psta->mac_id < 1 || psta->mac_id > (NUM_STA - 4)) {
  4823. DBG_8723A("r871x_set_stakey_hdl23a():set_stakey"
  4824. " failed, mac_id(aid) =%d\n",
  4825. psta->mac_id);
  4826. return H2C_REJECTED;
  4827. }
  4828. /* 0~3 for default key, cmd_id = macid + 3,
  4829. macid = aid+1; */
  4830. cam_id = psta->mac_id + 3;
  4831. DBG_8723A("Write CAM, mac_addr =%pM, "
  4832. "cam_entry =%d\n", pparm->addr, cam_id);
  4833. rtl8723a_cam_write(padapter, cam_id, ctrl,
  4834. pparm->addr, pparm->key);
  4835. return H2C_SUCCESS_RSP;
  4836. } else {
  4837. DBG_8723A("r871x_set_stakey_hdl23a(): sta has been "
  4838. "free\n");
  4839. return H2C_REJECTED;
  4840. }
  4841. }
  4842. /* below for sta mode */
  4843. if (pparm->algorithm == 0) { /* clear cam entry */
  4844. clear_cam_entry23a(padapter, pparm->id);
  4845. return H2C_SUCCESS;
  4846. }
  4847. ctrl = BIT(15) | (pparm->algorithm << 2);
  4848. rtl8723a_cam_write(padapter, cam_id, ctrl, pparm->addr, pparm->key);
  4849. pmlmeinfo->enc_algo = pparm->algorithm;
  4850. return H2C_SUCCESS;
  4851. }
  4852. int add_ba_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4853. {
  4854. const struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
  4855. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4856. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4857. struct sta_info *psta;
  4858. psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
  4859. if (!psta)
  4860. return H2C_SUCCESS;
  4861. if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
  4862. pmlmeinfo->HT_enable) ||
  4863. (pmlmeinfo->state & 0x03) == MSR_AP) {
  4864. issue_action_BA23a(padapter, pparm->addr,
  4865. WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
  4866. mod_timer(&psta->addba_retry_timer,
  4867. jiffies + msecs_to_jiffies(ADDBA_TO));
  4868. } else
  4869. psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
  4870. return H2C_SUCCESS;
  4871. }
  4872. int set_tx_beacon_cmd23a(struct rtw_adapter *padapter)
  4873. {
  4874. struct cmd_obj *ph2c;
  4875. struct Tx_Beacon_param *ptxBeacon_parm;
  4876. struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
  4877. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4878. struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  4879. u8 res = _SUCCESS;
  4880. int len_diff = 0;
  4881. ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
  4882. if (!ph2c) {
  4883. res = _FAIL;
  4884. goto exit;
  4885. }
  4886. ptxBeacon_parm = kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
  4887. if (!ptxBeacon_parm) {
  4888. kfree(ph2c);
  4889. res = _FAIL;
  4890. goto exit;
  4891. }
  4892. memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
  4893. sizeof(struct wlan_bssid_ex));
  4894. len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs,
  4895. ptxBeacon_parm->network.IELength,
  4896. pmlmeinfo->hidden_ssid_mode);
  4897. ptxBeacon_parm->network.IELength += len_diff;
  4898. init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm,
  4899. GEN_CMD_CODE(_TX_Beacon));
  4900. res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
  4901. exit:
  4902. return res;
  4903. }
  4904. int mlme_evt_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4905. {
  4906. u8 evt_code, evt_seq;
  4907. u16 evt_sz;
  4908. const struct C2HEvent_Header *c2h;
  4909. void (*event_callback)(struct rtw_adapter *dev, const u8 *pbuf);
  4910. c2h = (struct C2HEvent_Header *)pbuf;
  4911. evt_sz = c2h->len;
  4912. evt_seq = c2h->seq;
  4913. evt_code = c2h->ID;
  4914. /* checking if event code is valid */
  4915. if (evt_code >= MAX_C2HEVT) {
  4916. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
  4917. "Event Code(%d) mismatch!\n", evt_code);
  4918. goto _abort_event_;
  4919. }
  4920. /* checking if event size match the event parm size */
  4921. if (wlanevents[evt_code].parmsize != 0 &&
  4922. wlanevents[evt_code].parmsize != evt_sz) {
  4923. RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
  4924. "Event(%d) Parm Size mismatch (%d vs %d)!\n",
  4925. evt_code, wlanevents[evt_code].parmsize, evt_sz);
  4926. goto _abort_event_;
  4927. }
  4928. event_callback = wlanevents[evt_code].event_callback;
  4929. event_callback(padapter, pbuf + sizeof(struct C2HEvent_Header));
  4930. _abort_event_:
  4931. return H2C_SUCCESS;
  4932. }
  4933. int h2c_msg_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4934. {
  4935. if (!pbuf)
  4936. return H2C_PARAMETERS_ERROR;
  4937. return H2C_SUCCESS;
  4938. }
  4939. int tx_beacon_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4940. {
  4941. if (send_beacon23a(padapter) == _FAIL) {
  4942. DBG_8723A("issue_beacon23a, fail!\n");
  4943. return H2C_PARAMETERS_ERROR;
  4944. }
  4945. #ifdef CONFIG_8723AU_AP_MODE
  4946. else { /* tx bc/mc frames after update TIM */
  4947. struct sta_info *psta_bmc;
  4948. struct list_head *phead;
  4949. struct xmit_frame *pxmitframe, *ptmp;
  4950. struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
  4951. struct sta_priv *pstapriv = &padapter->stapriv;
  4952. /* for BC/MC Frames */
  4953. psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
  4954. if (!psta_bmc)
  4955. return H2C_SUCCESS;
  4956. if (pstapriv->tim_bitmap & BIT(0) && psta_bmc->sleepq_len > 0) {
  4957. msleep(10);/* 10ms, ATIM(HIQ) Windows */
  4958. /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
  4959. spin_lock_bh(&pxmitpriv->lock);
  4960. phead = get_list_head(&psta_bmc->sleep_q);
  4961. list_for_each_entry_safe(pxmitframe, ptmp,
  4962. phead, list) {
  4963. list_del_init(&pxmitframe->list);
  4964. psta_bmc->sleepq_len--;
  4965. if (psta_bmc->sleepq_len>0)
  4966. pxmitframe->attrib.mdata = 1;
  4967. else
  4968. pxmitframe->attrib.mdata = 0;
  4969. pxmitframe->attrib.triggered = 1;
  4970. pxmitframe->attrib.qsel = 0x11;/* HIQ */
  4971. rtl8723au_hal_xmitframe_enqueue(padapter,
  4972. pxmitframe);
  4973. }
  4974. /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
  4975. spin_unlock_bh(&pxmitpriv->lock);
  4976. }
  4977. }
  4978. #endif
  4979. return H2C_SUCCESS;
  4980. }
  4981. int set_ch_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4982. {
  4983. const struct set_ch_parm *set_ch_parm;
  4984. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  4985. if (!pbuf)
  4986. return H2C_PARAMETERS_ERROR;
  4987. set_ch_parm = (struct set_ch_parm *)pbuf;
  4988. DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__,
  4989. padapter->pnetdev->name, set_ch_parm->ch,
  4990. set_ch_parm->bw, set_ch_parm->ch_offset);
  4991. pmlmeext->cur_channel = set_ch_parm->ch;
  4992. pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
  4993. pmlmeext->cur_bwmode = set_ch_parm->bw;
  4994. set_channel_bwmode23a(padapter, set_ch_parm->ch,
  4995. set_ch_parm->ch_offset, set_ch_parm->bw);
  4996. return H2C_SUCCESS;
  4997. }
  4998. int set_chplan_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  4999. {
  5000. const struct SetChannelPlan_param *setChannelPlan_param;
  5001. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  5002. if (!pbuf)
  5003. return H2C_PARAMETERS_ERROR;
  5004. setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
  5005. pmlmeext->max_chan_nums =
  5006. init_channel_set(padapter, setChannelPlan_param->channel_plan,
  5007. pmlmeext->channel_set);
  5008. init_channel_list(padapter, pmlmeext->channel_set,
  5009. pmlmeext->max_chan_nums, &pmlmeext->channel_list);
  5010. return H2C_SUCCESS;
  5011. }
  5012. int led_blink_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  5013. {
  5014. struct LedBlink_param *ledBlink_param;
  5015. if (!pbuf)
  5016. return H2C_PARAMETERS_ERROR;
  5017. ledBlink_param = (struct LedBlink_param *)pbuf;
  5018. return H2C_SUCCESS;
  5019. }
  5020. int set_csa_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  5021. {
  5022. return H2C_REJECTED;
  5023. }
  5024. /* TDLS_WRCR : write RCR DATA BIT */
  5025. /* TDLS_SD_PTI : issue peer traffic indication */
  5026. /* TDLS_CS_OFF : go back to the channel linked with AP,
  5027. terminating channel switch procedure */
  5028. /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and
  5029. mgnt frame */
  5030. /* TDLS_DONE_CH_SEN : channel sensing and report candidate channel */
  5031. /* TDLS_OFF_CH : first time set channel to off channel */
  5032. /* TDLS_BASE_CH : go back tp the channel linked with AP when set
  5033. base channel as target channel */
  5034. /* TDLS_P_OFF_CH : periodically go to off channel */
  5035. /* TDLS_P_BASE_CH : periodically go back to base channel */
  5036. /* TDLS_RS_RCR : restore RCR */
  5037. /* TDLS_CKALV_PH1 : check alive timer phase1 */
  5038. /* TDLS_CKALV_PH2 : check alive timer phase2 */
  5039. /* TDLS_FREE_STA : free tdls sta */
  5040. int tdls_hdl23a(struct rtw_adapter *padapter, const u8 *pbuf)
  5041. {
  5042. return H2C_REJECTED;
  5043. }