rtw_cfgvendor.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2014 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. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #include <drv_types.h>
  21. #ifdef CONFIG_IOCTL_CFG80211
  22. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT)
  23. /*
  24. #include <linux/kernel.h>
  25. #include <linux/if_arp.h>
  26. #include <asm/uaccess.h>
  27. #include <linux/kernel.h>
  28. #include <linux/kthread.h>
  29. #include <linux/netdevice.h>
  30. #include <linux/sched.h>
  31. #include <linux/etherdevice.h>
  32. #include <linux/wireless.h>
  33. #include <linux/ieee80211.h>
  34. #include <linux/wait.h>
  35. #include <net/cfg80211.h>
  36. */
  37. #include <net/rtnetlink.h>
  38. #ifdef DBG_MEM_ALLOC
  39. extern bool match_mstat_sniff_rules(const enum mstat_f flags, const size_t size);
  40. struct sk_buff *dbg_rtw_cfg80211_vendor_event_alloc(struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp
  41. , const enum mstat_f flags, const char *func, const int line)
  42. {
  43. struct sk_buff *skb;
  44. unsigned int truesize = 0;
  45. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
  46. skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
  47. #else
  48. skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
  49. #endif
  50. if (skb)
  51. truesize = skb->truesize;
  52. if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
  53. RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);
  54. rtw_mstat_update(
  55. flags
  56. , skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
  57. , truesize
  58. );
  59. return skb;
  60. }
  61. void dbg_rtw_cfg80211_vendor_event(struct sk_buff *skb, gfp_t gfp
  62. , const enum mstat_f flags, const char *func, const int line)
  63. {
  64. unsigned int truesize = skb->truesize;
  65. if (match_mstat_sniff_rules(flags, truesize))
  66. RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);
  67. cfg80211_vendor_event(skb, gfp);
  68. rtw_mstat_update(
  69. flags
  70. , MSTAT_FREE
  71. , truesize
  72. );
  73. }
  74. struct sk_buff *dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int len
  75. , const enum mstat_f flags, const char *func, const int line)
  76. {
  77. struct sk_buff *skb;
  78. unsigned int truesize = 0;
  79. skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
  80. if (skb)
  81. truesize = skb->truesize;
  82. if (!skb || truesize < len || match_mstat_sniff_rules(flags, truesize))
  83. RTW_INFO("DBG_MEM_ALLOC %s:%d %s(%d), skb:%p, truesize=%u\n", func, line, __FUNCTION__, len, skb, truesize);
  84. rtw_mstat_update(
  85. flags
  86. , skb ? MSTAT_ALLOC_SUCCESS : MSTAT_ALLOC_FAIL
  87. , truesize
  88. );
  89. return skb;
  90. }
  91. int dbg_rtw_cfg80211_vendor_cmd_reply(struct sk_buff *skb
  92. , const enum mstat_f flags, const char *func, const int line)
  93. {
  94. unsigned int truesize = skb->truesize;
  95. int ret;
  96. if (match_mstat_sniff_rules(flags, truesize))
  97. RTW_INFO("DBG_MEM_ALLOC %s:%d %s, truesize=%u\n", func, line, __FUNCTION__, truesize);
  98. ret = cfg80211_vendor_cmd_reply(skb);
  99. rtw_mstat_update(
  100. flags
  101. , MSTAT_FREE
  102. , truesize
  103. );
  104. return ret;
  105. }
  106. #define rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp) \
  107. dbg_rtw_cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
  108. #define rtw_cfg80211_vendor_event(skb, gfp) \
  109. dbg_rtw_cfg80211_vendor_event(skb, gfp, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
  110. #define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
  111. dbg_rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
  112. #define rtw_cfg80211_vendor_cmd_reply(skb) \
  113. dbg_rtw_cfg80211_vendor_cmd_reply(skb, MSTAT_FUNC_CFG_VENDOR | MSTAT_TYPE_SKB, __FUNCTION__, __LINE__)
  114. #else
  115. struct sk_buff *rtw_cfg80211_vendor_event_alloc(
  116. struct wiphy *wiphy, struct wireless_dev *wdev, int len, int event_id, gfp_t gfp)
  117. {
  118. struct sk_buff *skb;
  119. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
  120. skb = cfg80211_vendor_event_alloc(wiphy, len, event_id, gfp);
  121. #else
  122. skb = cfg80211_vendor_event_alloc(wiphy, wdev, len, event_id, gfp);
  123. #endif
  124. return skb;
  125. }
  126. #define rtw_cfg80211_vendor_event(skb, gfp) \
  127. cfg80211_vendor_event(skb, gfp)
  128. #define rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len) \
  129. cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len)
  130. #define rtw_cfg80211_vendor_cmd_reply(skb) \
  131. cfg80211_vendor_cmd_reply(skb)
  132. #endif /* DBG_MEM_ALLOC */
  133. /*
  134. * This API is to be used for asynchronous vendor events. This
  135. * shouldn't be used in response to a vendor command from its
  136. * do_it handler context (instead rtw_cfgvendor_send_cmd_reply should
  137. * be used).
  138. */
  139. int rtw_cfgvendor_send_async_event(struct wiphy *wiphy,
  140. struct net_device *dev, int event_id, const void *data, int len)
  141. {
  142. u16 kflags;
  143. struct sk_buff *skb;
  144. kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
  145. /* Alloc the SKB for vendor_event */
  146. skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), len, event_id, kflags);
  147. if (!skb) {
  148. RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
  149. return -ENOMEM;
  150. }
  151. /* Push the data to the skb */
  152. nla_put_nohdr(skb, len, data);
  153. rtw_cfg80211_vendor_event(skb, kflags);
  154. return 0;
  155. }
  156. static int rtw_cfgvendor_send_cmd_reply(struct wiphy *wiphy,
  157. struct net_device *dev, const void *data, int len)
  158. {
  159. struct sk_buff *skb;
  160. /* Alloc the SKB for vendor_event */
  161. skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
  162. if (unlikely(!skb)) {
  163. RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(dev));
  164. return -ENOMEM;
  165. }
  166. /* Push the data to the skb */
  167. nla_put_nohdr(skb, len, data);
  168. return rtw_cfg80211_vendor_cmd_reply(skb);
  169. }
  170. #define WIFI_FEATURE_INFRA 0x0001 /* Basic infrastructure mode */
  171. #define WIFI_FEATURE_INFRA_5G 0x0002 /* Support for 5 GHz Band */
  172. #define WIFI_FEATURE_HOTSPOT 0x0004 /* Support for GAS/ANQP */
  173. #define WIFI_FEATURE_P2P 0x0008 /* Wifi-Direct */
  174. #define WIFI_FEATURE_SOFT_AP 0x0010 /* Soft AP */
  175. #define WIFI_FEATURE_GSCAN 0x0020 /* Google-Scan APIs */
  176. #define WIFI_FEATURE_NAN 0x0040 /* Neighbor Awareness Networking */
  177. #define WIFI_FEATURE_D2D_RTT 0x0080 /* Device-to-device RTT */
  178. #define WIFI_FEATURE_D2AP_RTT 0x0100 /* Device-to-AP RTT */
  179. #define WIFI_FEATURE_BATCH_SCAN 0x0200 /* Batched Scan (legacy) */
  180. #define WIFI_FEATURE_PNO 0x0400 /* Preferred network offload */
  181. #define WIFI_FEATURE_ADDITIONAL_STA 0x0800 /* Support for two STAs */
  182. #define WIFI_FEATURE_TDLS 0x1000 /* Tunnel directed link setup */
  183. #define WIFI_FEATURE_TDLS_OFFCHANNEL 0x2000 /* Support for TDLS off channel */
  184. #define WIFI_FEATURE_EPR 0x4000 /* Enhanced power reporting */
  185. #define WIFI_FEATURE_AP_STA 0x8000 /* Support for AP STA Concurrency */
  186. #define MAX_FEATURE_SET_CONCURRRENT_GROUPS 3
  187. #include <hal_data.h>
  188. int rtw_dev_get_feature_set(struct net_device *dev)
  189. {
  190. _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
  191. HAL_DATA_TYPE *HalData = GET_HAL_DATA(adapter);
  192. HAL_VERSION *hal_ver = &HalData->version_id;
  193. int feature_set = 0;
  194. feature_set |= WIFI_FEATURE_INFRA;
  195. if (IS_8814A_SERIES(*hal_ver) || IS_8812_SERIES(*hal_ver) ||
  196. IS_8821_SERIES(*hal_ver))
  197. feature_set |= WIFI_FEATURE_INFRA_5G;
  198. feature_set |= WIFI_FEATURE_P2P;
  199. feature_set |= WIFI_FEATURE_SOFT_AP;
  200. feature_set |= WIFI_FEATURE_ADDITIONAL_STA;
  201. return feature_set;
  202. }
  203. int *rtw_dev_get_feature_set_matrix(struct net_device *dev, int *num)
  204. {
  205. int feature_set_full, mem_needed;
  206. int *ret;
  207. *num = 0;
  208. mem_needed = sizeof(int) * MAX_FEATURE_SET_CONCURRRENT_GROUPS;
  209. ret = (int *)rtw_malloc(mem_needed);
  210. if (!ret) {
  211. RTW_ERR(FUNC_NDEV_FMT" failed to allocate %d bytes\n"
  212. , FUNC_NDEV_ARG(dev), mem_needed);
  213. return ret;
  214. }
  215. feature_set_full = rtw_dev_get_feature_set(dev);
  216. ret[0] = (feature_set_full & WIFI_FEATURE_INFRA) |
  217. (feature_set_full & WIFI_FEATURE_INFRA_5G) |
  218. (feature_set_full & WIFI_FEATURE_NAN) |
  219. (feature_set_full & WIFI_FEATURE_D2D_RTT) |
  220. (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
  221. (feature_set_full & WIFI_FEATURE_PNO) |
  222. (feature_set_full & WIFI_FEATURE_BATCH_SCAN) |
  223. (feature_set_full & WIFI_FEATURE_GSCAN) |
  224. (feature_set_full & WIFI_FEATURE_HOTSPOT) |
  225. (feature_set_full & WIFI_FEATURE_ADDITIONAL_STA) |
  226. (feature_set_full & WIFI_FEATURE_EPR);
  227. ret[1] = (feature_set_full & WIFI_FEATURE_INFRA) |
  228. (feature_set_full & WIFI_FEATURE_INFRA_5G) |
  229. /* Not yet verified NAN with P2P */
  230. /* (feature_set_full & WIFI_FEATURE_NAN) | */
  231. (feature_set_full & WIFI_FEATURE_P2P) |
  232. (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
  233. (feature_set_full & WIFI_FEATURE_D2D_RTT) |
  234. (feature_set_full & WIFI_FEATURE_EPR);
  235. ret[2] = (feature_set_full & WIFI_FEATURE_INFRA) |
  236. (feature_set_full & WIFI_FEATURE_INFRA_5G) |
  237. (feature_set_full & WIFI_FEATURE_NAN) |
  238. (feature_set_full & WIFI_FEATURE_D2D_RTT) |
  239. (feature_set_full & WIFI_FEATURE_D2AP_RTT) |
  240. (feature_set_full & WIFI_FEATURE_TDLS) |
  241. (feature_set_full & WIFI_FEATURE_TDLS_OFFCHANNEL) |
  242. (feature_set_full & WIFI_FEATURE_EPR);
  243. *num = MAX_FEATURE_SET_CONCURRRENT_GROUPS;
  244. return ret;
  245. }
  246. static int rtw_cfgvendor_get_feature_set(struct wiphy *wiphy,
  247. struct wireless_dev *wdev, const void *data, int len)
  248. {
  249. int err = 0;
  250. int reply;
  251. reply = rtw_dev_get_feature_set(wdev_to_ndev(wdev));
  252. err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), &reply, sizeof(int));
  253. if (unlikely(err))
  254. RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
  255. , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
  256. return err;
  257. }
  258. static int rtw_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy,
  259. struct wireless_dev *wdev, const void *data, int len)
  260. {
  261. int err = 0;
  262. struct sk_buff *skb;
  263. int *reply;
  264. int num, mem_needed, i;
  265. reply = rtw_dev_get_feature_set_matrix(wdev_to_ndev(wdev), &num);
  266. if (!reply) {
  267. RTW_ERR(FUNC_NDEV_FMT" Could not get feature list matrix\n"
  268. , FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
  269. err = -EINVAL;
  270. return err;
  271. }
  272. mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) +
  273. ATTRIBUTE_U32_LEN;
  274. /* Alloc the SKB for vendor_event */
  275. skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
  276. if (unlikely(!skb)) {
  277. RTW_ERR(FUNC_NDEV_FMT" skb alloc failed", FUNC_NDEV_ARG(wdev_to_ndev(wdev)));
  278. err = -ENOMEM;
  279. goto exit;
  280. }
  281. nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num);
  282. for (i = 0; i < num; i++)
  283. nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]);
  284. err = rtw_cfg80211_vendor_cmd_reply(skb);
  285. if (unlikely(err))
  286. RTW_ERR(FUNC_NDEV_FMT" Vendor Command reply failed ret:%d\n"
  287. , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
  288. exit:
  289. rtw_mfree((u8 *)reply, sizeof(int) * num);
  290. return err;
  291. }
  292. #if defined(GSCAN_SUPPORT) && 0
  293. int wl_cfgvendor_send_hotlist_event(struct wiphy *wiphy,
  294. struct net_device *dev, void *data, int len, wl_vendor_event_t event)
  295. {
  296. u16 kflags;
  297. const void *ptr;
  298. struct sk_buff *skb;
  299. int malloc_len, total, iter_cnt_to_send, cnt;
  300. gscan_results_cache_t *cache = (gscan_results_cache_t *)data;
  301. total = len / sizeof(wifi_gscan_result_t);
  302. while (total > 0) {
  303. malloc_len = (total * sizeof(wifi_gscan_result_t)) + VENDOR_DATA_OVERHEAD;
  304. if (malloc_len > NLMSG_DEFAULT_SIZE)
  305. malloc_len = NLMSG_DEFAULT_SIZE;
  306. iter_cnt_to_send =
  307. (malloc_len - VENDOR_DATA_OVERHEAD) / sizeof(wifi_gscan_result_t);
  308. total = total - iter_cnt_to_send;
  309. kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
  310. /* Alloc the SKB for vendor_event */
  311. skb = rtw_cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(dev), malloc_len, event, kflags);
  312. if (!skb) {
  313. WL_ERR(("skb alloc failed"));
  314. return -ENOMEM;
  315. }
  316. while (cache && iter_cnt_to_send) {
  317. ptr = (const void *) &cache->results[cache->tot_consumed];
  318. if (iter_cnt_to_send < (cache->tot_count - cache->tot_consumed))
  319. cnt = iter_cnt_to_send;
  320. else
  321. cnt = (cache->tot_count - cache->tot_consumed);
  322. iter_cnt_to_send -= cnt;
  323. cache->tot_consumed += cnt;
  324. /* Push the data to the skb */
  325. nla_append(skb, cnt * sizeof(wifi_gscan_result_t), ptr);
  326. if (cache->tot_consumed == cache->tot_count)
  327. cache = cache->next;
  328. }
  329. rtw_cfg80211_vendor_event(skb, kflags);
  330. }
  331. return 0;
  332. }
  333. static int wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy,
  334. struct wireless_dev *wdev, const void *data, int len)
  335. {
  336. int err = 0;
  337. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  338. dhd_pno_gscan_capabilities_t *reply = NULL;
  339. uint32 reply_len = 0;
  340. reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
  341. DHD_PNO_GET_CAPABILITIES, NULL, &reply_len);
  342. if (!reply) {
  343. WL_ERR(("Could not get capabilities\n"));
  344. err = -EINVAL;
  345. return err;
  346. }
  347. err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
  348. reply, reply_len);
  349. if (unlikely(err))
  350. WL_ERR(("Vendor Command reply failed ret:%d\n", err));
  351. kfree(reply);
  352. return err;
  353. }
  354. static int wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
  355. struct wireless_dev *wdev, const void *data, int len)
  356. {
  357. int err = 0, type, band;
  358. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  359. uint16 *reply = NULL;
  360. uint32 reply_len = 0, num_channels, mem_needed;
  361. struct sk_buff *skb;
  362. type = nla_type(data);
  363. if (type == GSCAN_ATTRIBUTE_BAND)
  364. band = nla_get_u32(data);
  365. else
  366. return -1;
  367. reply = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
  368. DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len);
  369. if (!reply) {
  370. WL_ERR(("Could not get channel list\n"));
  371. err = -EINVAL;
  372. return err;
  373. }
  374. num_channels = reply_len / sizeof(uint32);
  375. mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2);
  376. /* Alloc the SKB for vendor_event */
  377. skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
  378. if (unlikely(!skb)) {
  379. WL_ERR(("skb alloc failed"));
  380. err = -ENOMEM;
  381. goto exit;
  382. }
  383. nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels);
  384. nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply);
  385. err = rtw_cfg80211_vendor_cmd_reply(skb);
  386. if (unlikely(err))
  387. WL_ERR(("Vendor Command reply failed ret:%d\n", err));
  388. exit:
  389. kfree(reply);
  390. return err;
  391. }
  392. static int wl_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy,
  393. struct wireless_dev *wdev, const void *data, int len)
  394. {
  395. int err = 0;
  396. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  397. gscan_results_cache_t *results, *iter;
  398. uint32 reply_len, complete = 0, num_results_iter;
  399. int32 mem_needed;
  400. wifi_gscan_result_t *ptr;
  401. uint16 num_scan_ids, num_results;
  402. struct sk_buff *skb;
  403. struct nlattr *scan_hdr;
  404. dhd_dev_wait_batch_results_complete(bcmcfg_to_prmry_ndev(cfg));
  405. dhd_dev_pno_lock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
  406. results = dhd_dev_pno_get_gscan(bcmcfg_to_prmry_ndev(cfg),
  407. DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len);
  408. if (!results) {
  409. WL_ERR(("No results to send %d\n", err));
  410. err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
  411. results, 0);
  412. if (unlikely(err))
  413. WL_ERR(("Vendor Command reply failed ret:%d\n", err));
  414. dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
  415. return err;
  416. }
  417. num_scan_ids = reply_len & 0xFFFF;
  418. num_results = (reply_len & 0xFFFF0000) >> 16;
  419. mem_needed = (num_results * sizeof(wifi_gscan_result_t)) +
  420. (num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) +
  421. VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN;
  422. if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) {
  423. mem_needed = (int32)NLMSG_DEFAULT_SIZE;
  424. complete = 0;
  425. } else
  426. complete = 1;
  427. WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed,
  428. (int)NLMSG_DEFAULT_SIZE));
  429. /* Alloc the SKB for vendor_event */
  430. skb = rtw_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed);
  431. if (unlikely(!skb)) {
  432. WL_ERR(("skb alloc failed"));
  433. dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
  434. return -ENOMEM;
  435. }
  436. iter = results;
  437. nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, complete);
  438. mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD);
  439. while (iter && ((mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) > 0)) {
  440. scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS);
  441. nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id);
  442. nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag);
  443. num_results_iter =
  444. (mem_needed - GSCAN_BATCH_RESULT_HDR_LEN) / sizeof(wifi_gscan_result_t);
  445. if ((iter->tot_count - iter->tot_consumed) < num_results_iter)
  446. num_results_iter = iter->tot_count - iter->tot_consumed;
  447. nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter);
  448. if (num_results_iter) {
  449. ptr = &iter->results[iter->tot_consumed];
  450. iter->tot_consumed += num_results_iter;
  451. nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS,
  452. num_results_iter * sizeof(wifi_gscan_result_t), ptr);
  453. }
  454. nla_nest_end(skb, scan_hdr);
  455. mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN +
  456. (num_results_iter * sizeof(wifi_gscan_result_t));
  457. iter = iter->next;
  458. }
  459. dhd_dev_gscan_batch_cache_cleanup(bcmcfg_to_prmry_ndev(cfg));
  460. dhd_dev_pno_unlock_access_batch_results(bcmcfg_to_prmry_ndev(cfg));
  461. return rtw_cfg80211_vendor_cmd_reply(skb);
  462. }
  463. static int wl_cfgvendor_initiate_gscan(struct wiphy *wiphy,
  464. struct wireless_dev *wdev, const void *data, int len)
  465. {
  466. int err = 0;
  467. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  468. int type, tmp = len;
  469. int run = 0xFF;
  470. int flush = 0;
  471. const struct nlattr *iter;
  472. nla_for_each_attr(iter, data, len, tmp) {
  473. type = nla_type(iter);
  474. if (type == GSCAN_ATTRIBUTE_ENABLE_FEATURE)
  475. run = nla_get_u32(iter);
  476. else if (type == GSCAN_ATTRIBUTE_FLUSH_FEATURE)
  477. flush = nla_get_u32(iter);
  478. }
  479. if (run != 0xFF) {
  480. err = dhd_dev_pno_run_gscan(bcmcfg_to_prmry_ndev(cfg), run, flush);
  481. if (unlikely(err))
  482. WL_ERR(("Could not run gscan:%d\n", err));
  483. return err;
  484. } else
  485. return -1;
  486. }
  487. static int wl_cfgvendor_enable_full_scan_result(struct wiphy *wiphy,
  488. struct wireless_dev *wdev, const void *data, int len)
  489. {
  490. int err = 0;
  491. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  492. int type;
  493. bool real_time = FALSE;
  494. type = nla_type(data);
  495. if (type == GSCAN_ATTRIBUTE_ENABLE_FULL_SCAN_RESULTS) {
  496. real_time = nla_get_u32(data);
  497. err = dhd_dev_pno_enable_full_scan_result(bcmcfg_to_prmry_ndev(cfg), real_time);
  498. if (unlikely(err))
  499. WL_ERR(("Could not run gscan:%d\n", err));
  500. } else
  501. err = -1;
  502. return err;
  503. }
  504. static int wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy,
  505. struct wireless_dev *wdev, const void *data, int len)
  506. {
  507. int err = 0;
  508. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  509. gscan_scan_params_t *scan_param;
  510. int j = 0;
  511. int type, tmp, tmp1, tmp2, k = 0;
  512. const struct nlattr *iter, *iter1, *iter2;
  513. struct dhd_pno_gscan_channel_bucket *ch_bucket;
  514. scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL);
  515. if (!scan_param) {
  516. WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n"));
  517. err = -EINVAL;
  518. return err;
  519. }
  520. scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC;
  521. nla_for_each_attr(iter, data, len, tmp) {
  522. type = nla_type(iter);
  523. if (j >= GSCAN_MAX_CH_BUCKETS)
  524. break;
  525. switch (type) {
  526. case GSCAN_ATTRIBUTE_BASE_PERIOD:
  527. scan_param->scan_fr = nla_get_u32(iter) / 1000;
  528. break;
  529. case GSCAN_ATTRIBUTE_NUM_BUCKETS:
  530. scan_param->nchannel_buckets = nla_get_u32(iter);
  531. break;
  532. case GSCAN_ATTRIBUTE_CH_BUCKET_1:
  533. case GSCAN_ATTRIBUTE_CH_BUCKET_2:
  534. case GSCAN_ATTRIBUTE_CH_BUCKET_3:
  535. case GSCAN_ATTRIBUTE_CH_BUCKET_4:
  536. case GSCAN_ATTRIBUTE_CH_BUCKET_5:
  537. case GSCAN_ATTRIBUTE_CH_BUCKET_6:
  538. case GSCAN_ATTRIBUTE_CH_BUCKET_7:
  539. nla_for_each_nested(iter1, iter, tmp1) {
  540. type = nla_type(iter1);
  541. ch_bucket =
  542. scan_param->channel_bucket;
  543. switch (type) {
  544. case GSCAN_ATTRIBUTE_BUCKET_ID:
  545. break;
  546. case GSCAN_ATTRIBUTE_BUCKET_PERIOD:
  547. ch_bucket[j].bucket_freq_multiple =
  548. nla_get_u32(iter1) / 1000;
  549. break;
  550. case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS:
  551. ch_bucket[j].num_channels =
  552. nla_get_u32(iter1);
  553. break;
  554. case GSCAN_ATTRIBUTE_BUCKET_CHANNELS:
  555. nla_for_each_nested(iter2, iter1, tmp2) {
  556. if (k >= PFN_SWC_RSSI_WINDOW_MAX)
  557. break;
  558. ch_bucket[j].chan_list[k] =
  559. nla_get_u32(iter2);
  560. k++;
  561. }
  562. k = 0;
  563. break;
  564. case GSCAN_ATTRIBUTE_BUCKETS_BAND:
  565. ch_bucket[j].band = (uint16)
  566. nla_get_u32(iter1);
  567. break;
  568. case GSCAN_ATTRIBUTE_REPORT_EVENTS:
  569. ch_bucket[j].report_flag = (uint8)
  570. nla_get_u32(iter1);
  571. break;
  572. }
  573. }
  574. j++;
  575. break;
  576. }
  577. }
  578. if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
  579. DHD_PNO_SCAN_CFG_ID, scan_param, 0) < 0) {
  580. WL_ERR(("Could not set GSCAN scan cfg\n"));
  581. err = -EINVAL;
  582. }
  583. kfree(scan_param);
  584. return err;
  585. }
  586. static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy,
  587. struct wireless_dev *wdev, const void *data, int len)
  588. {
  589. int err = 0;
  590. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  591. gscan_hotlist_scan_params_t *hotlist_params;
  592. int tmp, tmp1, tmp2, type, j = 0, dummy;
  593. const struct nlattr *outer, *inner, *iter;
  594. uint8 flush = 0;
  595. struct bssid_t *pbssid;
  596. hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL);
  597. if (!hotlist_params) {
  598. WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
  599. return -1;
  600. }
  601. hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT;
  602. nla_for_each_attr(iter, data, len, tmp2) {
  603. type = nla_type(iter);
  604. switch (type) {
  605. case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS:
  606. pbssid = hotlist_params->bssid;
  607. nla_for_each_nested(outer, iter, tmp) {
  608. nla_for_each_nested(inner, outer, tmp1) {
  609. type = nla_type(inner);
  610. switch (type) {
  611. case GSCAN_ATTRIBUTE_BSSID:
  612. memcpy(&(pbssid[j].macaddr),
  613. nla_data(inner), ETHER_ADDR_LEN);
  614. break;
  615. case GSCAN_ATTRIBUTE_RSSI_LOW:
  616. pbssid[j].rssi_reporting_threshold =
  617. (int8) nla_get_u8(inner);
  618. break;
  619. case GSCAN_ATTRIBUTE_RSSI_HIGH:
  620. dummy = (int8) nla_get_u8(inner);
  621. break;
  622. }
  623. }
  624. j++;
  625. }
  626. hotlist_params->nbssid = j;
  627. break;
  628. case GSCAN_ATTRIBUTE_HOTLIST_FLUSH:
  629. flush = nla_get_u8(iter);
  630. break;
  631. case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
  632. hotlist_params->lost_ap_window = nla_get_u32(iter);
  633. break;
  634. }
  635. }
  636. if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
  637. DHD_PNO_GEOFENCE_SCAN_CFG_ID, hotlist_params, flush) < 0) {
  638. WL_ERR(("Could not set GSCAN HOTLIST cfg\n"));
  639. err = -EINVAL;
  640. goto exit;
  641. }
  642. exit:
  643. kfree(hotlist_params);
  644. return err;
  645. }
  646. static int wl_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy,
  647. struct wireless_dev *wdev, const void *data, int len)
  648. {
  649. int err = 0, tmp, type;
  650. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  651. gscan_batch_params_t batch_param;
  652. const struct nlattr *iter;
  653. batch_param.mscan = batch_param.bestn = 0;
  654. batch_param.buffer_threshold = GSCAN_BATCH_NO_THR_SET;
  655. nla_for_each_attr(iter, data, len, tmp) {
  656. type = nla_type(iter);
  657. switch (type) {
  658. case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN:
  659. batch_param.bestn = nla_get_u32(iter);
  660. break;
  661. case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE:
  662. batch_param.mscan = nla_get_u32(iter);
  663. break;
  664. case GSCAN_ATTRIBUTE_REPORT_THRESHOLD:
  665. batch_param.buffer_threshold = nla_get_u32(iter);
  666. break;
  667. }
  668. }
  669. if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
  670. DHD_PNO_BATCH_SCAN_CFG_ID, &batch_param, 0) < 0) {
  671. WL_ERR(("Could not set batch cfg\n"));
  672. err = -EINVAL;
  673. return err;
  674. }
  675. return err;
  676. }
  677. static int wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
  678. struct wireless_dev *wdev, const void *data, int len)
  679. {
  680. int err = 0;
  681. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  682. gscan_swc_params_t *significant_params;
  683. int tmp, tmp1, tmp2, type, j = 0;
  684. const struct nlattr *outer, *inner, *iter;
  685. uint8 flush = 0;
  686. wl_pfn_significant_bssid_t *pbssid;
  687. significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);
  688. if (!significant_params) {
  689. WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes\n", len));
  690. return -1;
  691. }
  692. nla_for_each_attr(iter, data, len, tmp2) {
  693. type = nla_type(iter);
  694. switch (type) {
  695. case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
  696. flush = nla_get_u8(iter);
  697. break;
  698. case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
  699. significant_params->rssi_window = nla_get_u16(iter);
  700. break;
  701. case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE:
  702. significant_params->lost_ap_window = nla_get_u16(iter);
  703. break;
  704. case GSCAN_ATTRIBUTE_MIN_BREACHING:
  705. significant_params->swc_threshold = nla_get_u16(iter);
  706. break;
  707. case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
  708. pbssid = significant_params->bssid_elem_list;
  709. nla_for_each_nested(outer, iter, tmp) {
  710. nla_for_each_nested(inner, outer, tmp1) {
  711. switch (nla_type(inner)) {
  712. case GSCAN_ATTRIBUTE_BSSID:
  713. memcpy(&(pbssid[j].macaddr),
  714. nla_data(inner),
  715. ETHER_ADDR_LEN);
  716. break;
  717. case GSCAN_ATTRIBUTE_RSSI_HIGH:
  718. pbssid[j].rssi_high_threshold =
  719. (int8) nla_get_u8(inner);
  720. break;
  721. case GSCAN_ATTRIBUTE_RSSI_LOW:
  722. pbssid[j].rssi_low_threshold =
  723. (int8) nla_get_u8(inner);
  724. break;
  725. }
  726. }
  727. j++;
  728. }
  729. break;
  730. }
  731. }
  732. significant_params->nbssid = j;
  733. if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
  734. DHD_PNO_SIGNIFICANT_SCAN_CFG_ID, significant_params, flush) < 0) {
  735. WL_ERR(("Could not set GSCAN significant cfg\n"));
  736. err = -EINVAL;
  737. goto exit;
  738. }
  739. exit:
  740. kfree(significant_params);
  741. return err;
  742. }
  743. #endif /* GSCAN_SUPPORT */
  744. #if defined(RTT_SUPPORT) && 0
  745. void wl_cfgvendor_rtt_evt(void *ctx, void *rtt_data)
  746. {
  747. struct wireless_dev *wdev = (struct wireless_dev *)ctx;
  748. struct wiphy *wiphy;
  749. struct sk_buff *skb;
  750. uint32 tot_len = NLMSG_DEFAULT_SIZE, entry_len = 0;
  751. gfp_t kflags;
  752. rtt_report_t *rtt_report = NULL;
  753. rtt_result_t *rtt_result = NULL;
  754. struct list_head *rtt_list;
  755. wiphy = wdev->wiphy;
  756. WL_DBG(("In\n"));
  757. /* Push the data to the skb */
  758. if (!rtt_data) {
  759. WL_ERR(("rtt_data is NULL\n"));
  760. goto exit;
  761. }
  762. rtt_list = (struct list_head *)rtt_data;
  763. kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
  764. /* Alloc the SKB for vendor_event */
  765. skb = rtw_cfg80211_vendor_event_alloc(wiphy, wdev, tot_len, GOOGLE_RTT_COMPLETE_EVENT, kflags);
  766. if (!skb) {
  767. WL_ERR(("skb alloc failed"));
  768. goto exit;
  769. }
  770. /* fill in the rtt results on each entry */
  771. list_for_each_entry(rtt_result, rtt_list, list) {
  772. entry_len = 0;
  773. if (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) {
  774. entry_len = sizeof(rtt_report_t);
  775. rtt_report = kzalloc(entry_len, kflags);
  776. if (!rtt_report) {
  777. WL_ERR(("rtt_report alloc failed"));
  778. goto exit;
  779. }
  780. rtt_report->addr = rtt_result->peer_mac;
  781. rtt_report->num_measurement = 1; /* ONE SHOT */
  782. rtt_report->status = rtt_result->err_code;
  783. rtt_report->type = (rtt_result->TOF_type == TOF_TYPE_ONE_WAY) ? RTT_ONE_WAY : RTT_TWO_WAY;
  784. rtt_report->peer = rtt_result->target_info->peer;
  785. rtt_report->channel = rtt_result->target_info->channel;
  786. rtt_report->rssi = rtt_result->avg_rssi;
  787. /* tx_rate */
  788. rtt_report->tx_rate = rtt_result->tx_rate;
  789. /* RTT */
  790. rtt_report->rtt = rtt_result->meanrtt;
  791. rtt_report->rtt_sd = rtt_result->sdrtt;
  792. /* convert to centi meter */
  793. if (rtt_result->distance != 0xffffffff)
  794. rtt_report->distance = (rtt_result->distance >> 2) * 25;
  795. else /* invalid distance */
  796. rtt_report->distance = -1;
  797. rtt_report->ts = rtt_result->ts;
  798. nla_append(skb, entry_len, rtt_report);
  799. kfree(rtt_report);
  800. }
  801. }
  802. rtw_cfg80211_vendor_event(skb, kflags);
  803. exit:
  804. return;
  805. }
  806. static int wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev,
  807. const void *data, int len)
  808. {
  809. int err = 0, rem, rem1, rem2, type;
  810. rtt_config_params_t rtt_param;
  811. rtt_target_info_t *rtt_target = NULL;
  812. const struct nlattr *iter, *iter1, *iter2;
  813. int8 eabuf[ETHER_ADDR_STR_LEN];
  814. int8 chanbuf[CHANSPEC_STR_LEN];
  815. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  816. WL_DBG(("In\n"));
  817. err = dhd_dev_rtt_register_noti_callback(wdev->netdev, wdev, wl_cfgvendor_rtt_evt);
  818. if (err < 0) {
  819. WL_ERR(("failed to register rtt_noti_callback\n"));
  820. goto exit;
  821. }
  822. memset(&rtt_param, 0, sizeof(rtt_param));
  823. nla_for_each_attr(iter, data, len, rem) {
  824. type = nla_type(iter);
  825. switch (type) {
  826. case RTT_ATTRIBUTE_TARGET_CNT:
  827. rtt_param.rtt_target_cnt = nla_get_u8(iter);
  828. if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) {
  829. WL_ERR(("exceed max target count : %d\n",
  830. rtt_param.rtt_target_cnt));
  831. err = BCME_RANGE;
  832. }
  833. break;
  834. case RTT_ATTRIBUTE_TARGET_INFO:
  835. rtt_target = rtt_param.target_info;
  836. nla_for_each_nested(iter1, iter, rem1) {
  837. nla_for_each_nested(iter2, iter1, rem2) {
  838. type = nla_type(iter2);
  839. switch (type) {
  840. case RTT_ATTRIBUTE_TARGET_MAC:
  841. memcpy(&rtt_target->addr, nla_data(iter2), ETHER_ADDR_LEN);
  842. break;
  843. case RTT_ATTRIBUTE_TARGET_TYPE:
  844. rtt_target->type = nla_get_u8(iter2);
  845. break;
  846. case RTT_ATTRIBUTE_TARGET_PEER:
  847. rtt_target->peer = nla_get_u8(iter2);
  848. break;
  849. case RTT_ATTRIBUTE_TARGET_CHAN:
  850. memcpy(&rtt_target->channel, nla_data(iter2),
  851. sizeof(rtt_target->channel));
  852. break;
  853. case RTT_ATTRIBUTE_TARGET_MODE:
  854. rtt_target->continuous = nla_get_u8(iter2);
  855. break;
  856. case RTT_ATTRIBUTE_TARGET_INTERVAL:
  857. rtt_target->interval = nla_get_u32(iter2);
  858. break;
  859. case RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT:
  860. rtt_target->measure_cnt = nla_get_u32(iter2);
  861. break;
  862. case RTT_ATTRIBUTE_TARGET_NUM_PKT:
  863. rtt_target->ftm_cnt = nla_get_u32(iter2);
  864. break;
  865. case RTT_ATTRIBUTE_TARGET_NUM_RETRY:
  866. rtt_target->retry_cnt = nla_get_u32(iter2);
  867. }
  868. }
  869. /* convert to chanspec value */
  870. rtt_target->chanspec = dhd_rtt_convert_to_chspec(rtt_target->channel);
  871. if (rtt_target->chanspec == 0) {
  872. WL_ERR(("Channel is not valid\n"));
  873. goto exit;
  874. }
  875. WL_INFORM(("Target addr %s, Channel : %s for RTT\n",
  876. bcm_ether_ntoa((const struct ether_addr *)&rtt_target->addr, eabuf),
  877. wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
  878. rtt_target++;
  879. }
  880. break;
  881. }
  882. }
  883. WL_DBG(("leave :target_cnt : %d\n", rtt_param.rtt_target_cnt));
  884. if (dhd_dev_rtt_set_cfg(bcmcfg_to_prmry_ndev(cfg), &rtt_param) < 0) {
  885. WL_ERR(("Could not set RTT configuration\n"));
  886. err = -EINVAL;
  887. }
  888. exit:
  889. return err;
  890. }
  891. static int wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev,
  892. const void *data, int len)
  893. {
  894. int err = 0, rem, type, target_cnt = 0;
  895. const struct nlattr *iter;
  896. struct ether_addr *mac_list = NULL, *mac_addr = NULL;
  897. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  898. nla_for_each_attr(iter, data, len, rem) {
  899. type = nla_type(iter);
  900. switch (type) {
  901. case RTT_ATTRIBUTE_TARGET_CNT:
  902. target_cnt = nla_get_u8(iter);
  903. mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN , GFP_KERNEL);
  904. if (mac_list == NULL) {
  905. WL_ERR(("failed to allocate mem for mac list\n"));
  906. goto exit;
  907. }
  908. mac_addr = &mac_list[0];
  909. break;
  910. case RTT_ATTRIBUTE_TARGET_MAC:
  911. if (mac_addr)
  912. memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN);
  913. else {
  914. WL_ERR(("mac_list is NULL\n"));
  915. goto exit;
  916. }
  917. break;
  918. }
  919. if (dhd_dev_rtt_cancel_cfg(bcmcfg_to_prmry_ndev(cfg), mac_list, target_cnt) < 0) {
  920. WL_ERR(("Could not cancel RTT configuration\n"));
  921. err = -EINVAL;
  922. goto exit;
  923. }
  924. }
  925. exit:
  926. if (mac_list)
  927. kfree(mac_list);
  928. return err;
  929. }
  930. static int wl_cfgvendor_rtt_get_capability(struct wiphy *wiphy, struct wireless_dev *wdev,
  931. const void *data, int len)
  932. {
  933. int err = 0;
  934. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  935. rtt_capabilities_t capability;
  936. err = dhd_dev_rtt_capability(bcmcfg_to_prmry_ndev(cfg), &capability);
  937. if (unlikely(err)) {
  938. WL_ERR(("Vendor Command reply failed ret:%d\n", err));
  939. goto exit;
  940. }
  941. err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
  942. &capability, sizeof(capability));
  943. if (unlikely(err))
  944. WL_ERR(("Vendor Command reply failed ret:%d\n", err));
  945. exit:
  946. return err;
  947. }
  948. #endif /* RTT_SUPPORT */
  949. static int wl_cfgvendor_priv_string_handler(struct wiphy *wiphy,
  950. struct wireless_dev *wdev, const void *data, int len)
  951. {
  952. int err = 0;
  953. u8 resp[1] = {'\0'};
  954. RTW_PRINT(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(wdev_to_ndev(wdev)), (char *)data);
  955. err = rtw_cfgvendor_send_cmd_reply(wiphy, wdev_to_ndev(wdev), resp, 1);
  956. if (unlikely(err))
  957. RTW_ERR(FUNC_NDEV_FMT"Vendor Command reply failed ret:%d\n"
  958. , FUNC_NDEV_ARG(wdev_to_ndev(wdev)), err);
  959. return err;
  960. #if 0
  961. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  962. int err = 0;
  963. int data_len = 0;
  964. bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
  965. if (strncmp((char *)data, BRCM_VENDOR_SCMD_CAPA, strlen(BRCM_VENDOR_SCMD_CAPA)) == 0) {
  966. err = wldev_iovar_getbuf(bcmcfg_to_prmry_ndev(cfg), "cap", NULL, 0,
  967. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  968. if (unlikely(err)) {
  969. WL_ERR(("error (%d)\n", err));
  970. return err;
  971. }
  972. data_len = strlen(cfg->ioctl_buf);
  973. cfg->ioctl_buf[data_len] = '\0';
  974. }
  975. err = rtw_cfgvendor_send_cmd_reply(wiphy, bcmcfg_to_prmry_ndev(cfg),
  976. cfg->ioctl_buf, data_len + 1);
  977. if (unlikely(err))
  978. WL_ERR(("Vendor Command reply failed ret:%d\n", err));
  979. else
  980. WL_INFORM(("Vendor Command reply sent successfully!\n"));
  981. return err;
  982. #endif
  983. }
  984. static const struct wiphy_vendor_command rtw_vendor_cmds[] = {
  985. {
  986. {
  987. .vendor_id = OUI_BRCM,
  988. .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
  989. },
  990. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  991. .doit = wl_cfgvendor_priv_string_handler
  992. },
  993. #if defined(GSCAN_SUPPORT) && 0
  994. {
  995. {
  996. .vendor_id = OUI_GOOGLE,
  997. .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
  998. },
  999. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1000. .doit = wl_cfgvendor_gscan_get_capabilities
  1001. },
  1002. {
  1003. {
  1004. .vendor_id = OUI_GOOGLE,
  1005. .subcmd = GSCAN_SUBCMD_SET_CONFIG
  1006. },
  1007. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1008. .doit = wl_cfgvendor_set_scan_cfg
  1009. },
  1010. {
  1011. {
  1012. .vendor_id = OUI_GOOGLE,
  1013. .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
  1014. },
  1015. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1016. .doit = wl_cfgvendor_set_batch_scan_cfg
  1017. },
  1018. {
  1019. {
  1020. .vendor_id = OUI_GOOGLE,
  1021. .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
  1022. },
  1023. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1024. .doit = wl_cfgvendor_initiate_gscan
  1025. },
  1026. {
  1027. {
  1028. .vendor_id = OUI_GOOGLE,
  1029. .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
  1030. },
  1031. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1032. .doit = wl_cfgvendor_enable_full_scan_result
  1033. },
  1034. {
  1035. {
  1036. .vendor_id = OUI_GOOGLE,
  1037. .subcmd = GSCAN_SUBCMD_SET_HOTLIST
  1038. },
  1039. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1040. .doit = wl_cfgvendor_hotlist_cfg
  1041. },
  1042. {
  1043. {
  1044. .vendor_id = OUI_GOOGLE,
  1045. .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG
  1046. },
  1047. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1048. .doit = wl_cfgvendor_significant_change_cfg
  1049. },
  1050. {
  1051. {
  1052. .vendor_id = OUI_GOOGLE,
  1053. .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
  1054. },
  1055. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1056. .doit = wl_cfgvendor_gscan_get_batch_results
  1057. },
  1058. {
  1059. {
  1060. .vendor_id = OUI_GOOGLE,
  1061. .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
  1062. },
  1063. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1064. .doit = wl_cfgvendor_gscan_get_channel_list
  1065. },
  1066. #endif /* GSCAN_SUPPORT */
  1067. #if defined(RTT_SUPPORT) && 0
  1068. {
  1069. {
  1070. .vendor_id = OUI_GOOGLE,
  1071. .subcmd = RTT_SUBCMD_SET_CONFIG
  1072. },
  1073. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1074. .doit = wl_cfgvendor_rtt_set_config
  1075. },
  1076. {
  1077. {
  1078. .vendor_id = OUI_GOOGLE,
  1079. .subcmd = RTT_SUBCMD_CANCEL_CONFIG
  1080. },
  1081. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1082. .doit = wl_cfgvendor_rtt_cancel_config
  1083. },
  1084. {
  1085. {
  1086. .vendor_id = OUI_GOOGLE,
  1087. .subcmd = RTT_SUBCMD_GETCAPABILITY
  1088. },
  1089. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1090. .doit = wl_cfgvendor_rtt_get_capability
  1091. },
  1092. #endif /* RTT_SUPPORT */
  1093. {
  1094. {
  1095. .vendor_id = OUI_GOOGLE,
  1096. .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
  1097. },
  1098. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1099. .doit = rtw_cfgvendor_get_feature_set
  1100. },
  1101. {
  1102. {
  1103. .vendor_id = OUI_GOOGLE,
  1104. .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
  1105. },
  1106. .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
  1107. .doit = rtw_cfgvendor_get_feature_set_matrix
  1108. }
  1109. };
  1110. static const struct nl80211_vendor_cmd_info rtw_vendor_events[] = {
  1111. { OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC },
  1112. { OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR },
  1113. #if defined(GSCAN_SUPPORT) && 0
  1114. { OUI_GOOGLE, GOOGLE_GSCAN_SIGNIFICANT_EVENT },
  1115. { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT },
  1116. { OUI_GOOGLE, GOOGLE_GSCAN_BATCH_SCAN_EVENT },
  1117. { OUI_GOOGLE, GOOGLE_SCAN_FULL_RESULTS_EVENT },
  1118. #endif /* GSCAN_SUPPORT */
  1119. #if defined(RTT_SUPPORT) && 0
  1120. { OUI_GOOGLE, GOOGLE_RTT_COMPLETE_EVENT },
  1121. #endif /* RTT_SUPPORT */
  1122. #if defined(GSCAN_SUPPORT) && 0
  1123. { OUI_GOOGLE, GOOGLE_SCAN_COMPLETE_EVENT },
  1124. { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT }
  1125. #endif /* GSCAN_SUPPORT */
  1126. };
  1127. int rtw_cfgvendor_attach(struct wiphy *wiphy)
  1128. {
  1129. RTW_INFO("Register RTW cfg80211 vendor cmd(0x%x) interface\n", NL80211_CMD_VENDOR);
  1130. wiphy->vendor_commands = rtw_vendor_cmds;
  1131. wiphy->n_vendor_commands = ARRAY_SIZE(rtw_vendor_cmds);
  1132. wiphy->vendor_events = rtw_vendor_events;
  1133. wiphy->n_vendor_events = ARRAY_SIZE(rtw_vendor_events);
  1134. return 0;
  1135. }
  1136. int rtw_cfgvendor_detach(struct wiphy *wiphy)
  1137. {
  1138. RTW_INFO("Vendor: Unregister RTW cfg80211 vendor interface\n");
  1139. wiphy->vendor_commands = NULL;
  1140. wiphy->vendor_events = NULL;
  1141. wiphy->n_vendor_commands = 0;
  1142. wiphy->n_vendor_events = 0;
  1143. return 0;
  1144. }
  1145. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(RTW_VENDOR_EXT_SUPPORT) */
  1146. #endif /* CONFIG_IOCTL_CFG80211 */