rtw_android.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2017 Realtek Corporation.
  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. #ifdef CONFIG_GPIO_WAKEUP
  16. #include <linux/gpio.h>
  17. #endif
  18. #include <drv_types.h>
  19. #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
  20. #include <linux/platform_device.h>
  21. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
  22. #include <linux/wlan_plat.h>
  23. #else
  24. #include <linux/wifi_tiwlan.h>
  25. #endif
  26. #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
  27. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
  28. #define strnicmp strncasecmp
  29. #endif /* Linux kernel >= 4.0.0 */
  30. #ifdef CONFIG_GPIO_WAKEUP
  31. #include <linux/interrupt.h>
  32. #include <linux/irq.h>
  33. #endif
  34. #include "rtw_version.h"
  35. extern void macstr2num(u8 *dst, u8 *src);
  36. const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
  37. "START",
  38. "STOP",
  39. "SCAN-ACTIVE",
  40. "SCAN-PASSIVE",
  41. "RSSI",
  42. "LINKSPEED",
  43. "RXFILTER-START",
  44. "RXFILTER-STOP",
  45. "RXFILTER-ADD",
  46. "RXFILTER-REMOVE",
  47. "BTCOEXSCAN-START",
  48. "BTCOEXSCAN-STOP",
  49. "BTCOEXMODE",
  50. "SETSUSPENDOPT",
  51. "P2P_DEV_ADDR",
  52. "SETFWPATH",
  53. "SETBAND",
  54. "GETBAND",
  55. "COUNTRY",
  56. "P2P_SET_NOA",
  57. "P2P_GET_NOA",
  58. "P2P_SET_PS",
  59. "SET_AP_WPS_P2P_IE",
  60. "MIRACAST",
  61. #ifdef CONFIG_PNO_SUPPORT
  62. "PNOSSIDCLR",
  63. "PNOSETUP",
  64. "PNOFORCE",
  65. "PNODEBUG",
  66. #endif
  67. "MACADDR",
  68. "BLOCK_SCAN",
  69. "BLOCK",
  70. "WFD-ENABLE",
  71. "WFD-DISABLE",
  72. "WFD-SET-TCPPORT",
  73. "WFD-SET-MAXTPUT",
  74. "WFD-SET-DEVTYPE",
  75. "SET_DTIM",
  76. "HOSTAPD_SET_MACADDR_ACL",
  77. "HOSTAPD_ACL_ADD_STA",
  78. "HOSTAPD_ACL_REMOVE_STA",
  79. #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
  80. "GTK_REKEY_OFFLOAD",
  81. #endif /* CONFIG_GTK_OL */
  82. /* Private command for P2P disable*/
  83. "P2P_DISABLE",
  84. "SET_AEK",
  85. "DRIVER_VERSION"
  86. };
  87. #ifdef CONFIG_PNO_SUPPORT
  88. #define PNO_TLV_PREFIX 'S'
  89. #define PNO_TLV_VERSION '1'
  90. #define PNO_TLV_SUBVERSION '2'
  91. #define PNO_TLV_RESERVED '0'
  92. #define PNO_TLV_TYPE_SSID_IE 'S'
  93. #define PNO_TLV_TYPE_TIME 'T'
  94. #define PNO_TLV_FREQ_REPEAT 'R'
  95. #define PNO_TLV_FREQ_EXPO_MAX 'M'
  96. typedef struct cmd_tlv {
  97. char prefix;
  98. char version;
  99. char subver;
  100. char reserved;
  101. } cmd_tlv_t;
  102. #ifdef CONFIG_PNO_SET_DEBUG
  103. char pno_in_example[] = {
  104. 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
  105. 'S', '1', '2', '0',
  106. 'S', /* 1 */
  107. 0x05,
  108. 'd', 'l', 'i', 'n', 'k',
  109. 'S', /* 2 */
  110. 0x06,
  111. 'B', 'U', 'F', 'B', 'U', 'F',
  112. 'S', /* 3 */
  113. 0x20,
  114. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '@', '#', '$', '%', '^',
  115. 'S', /* 4 */
  116. 0x0a,
  117. '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  118. 'T',
  119. '0', '5',
  120. 'R',
  121. '2',
  122. 'M',
  123. '2',
  124. 0x00
  125. };
  126. #endif /* CONFIG_PNO_SET_DEBUG */
  127. #endif /* PNO_SUPPORT */
  128. typedef struct android_wifi_priv_cmd {
  129. char *buf;
  130. int used_len;
  131. int total_len;
  132. } android_wifi_priv_cmd;
  133. #ifdef CONFIG_COMPAT
  134. typedef struct compat_android_wifi_priv_cmd {
  135. compat_uptr_t buf;
  136. int used_len;
  137. int total_len;
  138. } compat_android_wifi_priv_cmd;
  139. #endif /* CONFIG_COMPAT */
  140. /**
  141. * Local (static) functions and variables
  142. */
  143. /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
  144. * time (only) in dhd_open, subsequential wifi on will be handled by
  145. * wl_android_wifi_on
  146. */
  147. static int g_wifi_on = _TRUE;
  148. unsigned int oob_irq = 0;
  149. unsigned int oob_gpio = 0;
  150. #ifdef CONFIG_PNO_SUPPORT
  151. /*
  152. * rtw_android_pno_setup
  153. * Description:
  154. * This is used for private command.
  155. *
  156. * Parameter:
  157. * net: net_device
  158. * command: parameters from private command
  159. * total_len: the length of the command.
  160. *
  161. * */
  162. static int rtw_android_pno_setup(struct net_device *net, char *command, int total_len)
  163. {
  164. pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
  165. int res = -1;
  166. int nssid = 0;
  167. cmd_tlv_t *cmd_tlv_temp;
  168. char *str_ptr;
  169. int tlv_size_left;
  170. int pno_time = 0;
  171. int pno_repeat = 0;
  172. int pno_freq_expo_max = 0;
  173. int cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOSETUP_SET]) + 1;
  174. #ifdef CONFIG_PNO_SET_DEBUG
  175. int i;
  176. char *p;
  177. p = pno_in_example;
  178. total_len = sizeof(pno_in_example);
  179. str_ptr = p + cmdlen;
  180. #else
  181. str_ptr = command + cmdlen;
  182. #endif
  183. if (total_len < (cmdlen + sizeof(cmd_tlv_t))) {
  184. RTW_INFO("%s argument=%d less min size\n", __func__, total_len);
  185. goto exit_proc;
  186. }
  187. tlv_size_left = total_len - cmdlen;
  188. cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
  189. memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
  190. if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
  191. (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
  192. (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
  193. str_ptr += sizeof(cmd_tlv_t);
  194. tlv_size_left -= sizeof(cmd_tlv_t);
  195. nssid = rtw_parse_ssid_list_tlv(&str_ptr, pno_ssids_local,
  196. MAX_PNO_LIST_COUNT, &tlv_size_left);
  197. if (nssid <= 0) {
  198. RTW_INFO("SSID is not presented or corrupted ret=%d\n", nssid);
  199. goto exit_proc;
  200. } else {
  201. if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
  202. RTW_INFO("%s scan duration corrupted field size %d\n",
  203. __func__, tlv_size_left);
  204. goto exit_proc;
  205. }
  206. str_ptr++;
  207. pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
  208. RTW_INFO("%s: pno_time=%d\n", __func__, pno_time);
  209. if (str_ptr[0] != 0) {
  210. if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
  211. RTW_INFO("%s pno repeat : corrupted field\n",
  212. __func__);
  213. goto exit_proc;
  214. }
  215. str_ptr++;
  216. pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
  217. RTW_INFO("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat);
  218. if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
  219. RTW_INFO("%s FREQ_EXPO_MAX corrupted field size\n",
  220. __func__);
  221. goto exit_proc;
  222. }
  223. str_ptr++;
  224. pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
  225. RTW_INFO("%s: pno_freq_expo_max=%d\n",
  226. __func__, pno_freq_expo_max);
  227. }
  228. }
  229. } else {
  230. RTW_INFO("%s get wrong TLV command\n", __FUNCTION__);
  231. goto exit_proc;
  232. }
  233. res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
  234. #ifdef CONFIG_PNO_SET_DEBUG
  235. rtw_dev_pno_debug(net);
  236. #endif
  237. exit_proc:
  238. return res;
  239. }
  240. /*
  241. * rtw_android_cfg80211_pno_setup
  242. * Description:
  243. * This is used for cfg80211 sched_scan.
  244. *
  245. * Parameter:
  246. * net: net_device
  247. * request: cfg80211_request
  248. * */
  249. int rtw_android_cfg80211_pno_setup(struct net_device *net,
  250. struct cfg80211_ssid *ssids, int n_ssids, int interval)
  251. {
  252. int res = -1;
  253. int nssid = 0;
  254. int pno_time = 0;
  255. int pno_repeat = 0;
  256. int pno_freq_expo_max = 0;
  257. int index = 0;
  258. pno_ssid_t pno_ssids_local[MAX_PNO_LIST_COUNT];
  259. if (n_ssids > MAX_PNO_LIST_COUNT || n_ssids < 0) {
  260. RTW_INFO("%s: nssids(%d) is invalid.\n", __func__, n_ssids);
  261. return -EINVAL;
  262. }
  263. memset(pno_ssids_local, 0, sizeof(pno_ssids_local));
  264. nssid = n_ssids;
  265. for (index = 0 ; index < nssid ; index++) {
  266. pno_ssids_local[index].SSID_len = ssids[index].ssid_len;
  267. memcpy(pno_ssids_local[index].SSID, ssids[index].ssid,
  268. ssids[index].ssid_len);
  269. }
  270. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
  271. if(ssids)
  272. rtw_mfree((u8 *)ssids, (n_ssids * sizeof(struct cfg80211_ssid)));
  273. #endif
  274. pno_time = (interval / 1000);
  275. RTW_INFO("%s: nssids: %d, pno_time=%d\n", __func__, nssid, pno_time);
  276. res = rtw_dev_pno_set(net, pno_ssids_local, nssid, pno_time,
  277. pno_repeat, pno_freq_expo_max);
  278. #ifdef CONFIG_PNO_SET_DEBUG
  279. rtw_dev_pno_debug(net);
  280. #endif
  281. exit_proc:
  282. return res;
  283. }
  284. int rtw_android_pno_enable(struct net_device *net, int pno_enable)
  285. {
  286. _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
  287. struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
  288. if (pwrctl) {
  289. pwrctl->wowlan_pno_enable = pno_enable;
  290. RTW_INFO("%s: wowlan_pno_enable: %d\n", __func__, pwrctl->wowlan_pno_enable);
  291. if (pwrctl->wowlan_pno_enable == 0) {
  292. if (pwrctl->pnlo_info != NULL) {
  293. rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
  294. pwrctl->pnlo_info = NULL;
  295. }
  296. if (pwrctl->pno_ssid_list != NULL) {
  297. rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
  298. pwrctl->pno_ssid_list = NULL;
  299. }
  300. if (pwrctl->pscan_info != NULL) {
  301. rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
  302. pwrctl->pscan_info = NULL;
  303. }
  304. }
  305. return 0;
  306. } else
  307. return -1;
  308. }
  309. #endif /* CONFIG_PNO_SUPPORT */
  310. int rtw_android_cmdstr_to_num(char *cmdstr)
  311. {
  312. int cmd_num;
  313. for (cmd_num = 0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
  314. if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])))
  315. break;
  316. return cmd_num;
  317. }
  318. int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
  319. {
  320. _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
  321. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  322. struct wlan_network *pcur_network = &pmlmepriv->cur_network;
  323. int bytes_written = 0;
  324. if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
  325. bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
  326. pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
  327. }
  328. return bytes_written;
  329. }
  330. int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
  331. {
  332. _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
  333. int bytes_written = 0;
  334. u16 link_speed = 0;
  335. link_speed = rtw_get_cur_max_rate(padapter) / 10;
  336. bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
  337. return bytes_written;
  338. }
  339. int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
  340. {
  341. int bytes_written = 0;
  342. bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
  343. return bytes_written;
  344. }
  345. int rtw_android_set_country(struct net_device *net, char *command, int total_len)
  346. {
  347. _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
  348. char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
  349. int ret = _FAIL;
  350. ret = rtw_set_country(adapter, country_code);
  351. return (ret == _SUCCESS) ? 0 : -1;
  352. }
  353. int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
  354. {
  355. int bytes_written = 0;
  356. /* We use the same address as our HW MAC address */
  357. _rtw_memcpy(command, net->dev_addr, ETH_ALEN);
  358. bytes_written = ETH_ALEN;
  359. return bytes_written;
  360. }
  361. int rtw_android_set_block_scan(struct net_device *net, char *command, int total_len)
  362. {
  363. _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
  364. char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK_SCAN]) + 1;
  365. #ifdef CONFIG_IOCTL_CFG80211
  366. adapter_wdev_data(adapter)->block_scan = (*block_value == '0') ? _FALSE : _TRUE;
  367. #endif
  368. return 0;
  369. }
  370. int rtw_android_set_block(struct net_device *net, char *command, int total_len)
  371. {
  372. _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
  373. char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
  374. #ifdef CONFIG_IOCTL_CFG80211
  375. adapter_wdev_data(adapter)->block = (*block_value == '0') ? _FALSE : _TRUE;
  376. #endif
  377. return 0;
  378. }
  379. int rtw_android_setband(struct net_device *net, char *command, int total_len)
  380. {
  381. _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
  382. char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SETBAND]) + 1;
  383. u32 band = WIFI_FREQUENCY_BAND_AUTO;
  384. int ret = _FAIL;
  385. if (sscanf(arg, "%u", &band) >= 1)
  386. ret = rtw_set_band(adapter, band);
  387. return (ret == _SUCCESS) ? 0 : -1;
  388. }
  389. int rtw_android_getband(struct net_device *net, char *command, int total_len)
  390. {
  391. _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
  392. int bytes_written = 0;
  393. bytes_written = snprintf(command, total_len, "%u", adapter->setband);
  394. return bytes_written;
  395. }
  396. #ifdef CONFIG_WFD
  397. int rtw_android_set_miracast_mode(struct net_device *net, char *command, int total_len)
  398. {
  399. _adapter *adapter = (_adapter *)rtw_netdev_priv(net);
  400. struct wifi_display_info *wfd_info = &adapter->wfd_info;
  401. char *arg = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_MIRACAST]) + 1;
  402. u8 mode;
  403. int num;
  404. int ret = _FAIL;
  405. num = sscanf(arg, "%hhu", &mode);
  406. if (num < 1)
  407. goto exit;
  408. switch (mode) {
  409. case 1: /* soruce */
  410. mode = MIRACAST_SOURCE;
  411. break;
  412. case 2: /* sink */
  413. mode = MIRACAST_SINK;
  414. break;
  415. case 0: /* disabled */
  416. default:
  417. mode = MIRACAST_DISABLED;
  418. break;
  419. }
  420. wfd_info->stack_wfd_mode = mode;
  421. RTW_INFO("stack miracast mode: %s\n", get_miracast_mode_str(wfd_info->stack_wfd_mode));
  422. ret = _SUCCESS;
  423. exit:
  424. return (ret == _SUCCESS) ? 0 : -1;
  425. }
  426. #endif /* CONFIG_WFD */
  427. int get_int_from_command(char *pcmd)
  428. {
  429. int i = 0;
  430. for (i = 0; i < strlen(pcmd); i++) {
  431. if (pcmd[i] == '=') {
  432. /* Skip the '=' and space characters. */
  433. i += 2;
  434. break;
  435. }
  436. }
  437. return rtw_atoi(pcmd + i) ;
  438. }
  439. #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
  440. int rtw_gtk_offload(struct net_device *net, u8 *cmd_ptr)
  441. {
  442. int i;
  443. /* u8 *cmd_ptr = priv_cmd.buf; */
  444. struct sta_info *psta;
  445. _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
  446. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  447. struct sta_priv *pstapriv = &padapter->stapriv;
  448. struct security_priv *psecuritypriv = &(padapter->securitypriv);
  449. psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
  450. if (psta == NULL)
  451. RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
  452. else {
  453. /* string command length of "GTK_REKEY_OFFLOAD" */
  454. cmd_ptr += 18;
  455. _rtw_memcpy(psta->kek, cmd_ptr, RTW_KEK_LEN);
  456. cmd_ptr += RTW_KEK_LEN;
  457. /*
  458. printk("supplicant KEK: ");
  459. for(i=0;i<RTW_KEK_LEN; i++)
  460. printk(" %02x ", psta->kek[i]);
  461. printk("\n supplicant KCK: ");
  462. */
  463. _rtw_memcpy(psta->kck, cmd_ptr, RTW_KCK_LEN);
  464. cmd_ptr += RTW_KCK_LEN;
  465. /*
  466. for(i=0;i<RTW_KEK_LEN; i++)
  467. printk(" %02x ", psta->kck[i]);
  468. */
  469. _rtw_memcpy(psta->replay_ctr, cmd_ptr, RTW_REPLAY_CTR_LEN);
  470. psecuritypriv->binstallKCK_KEK = _TRUE;
  471. /* printk("\nREPLAY_CTR: "); */
  472. /* for(i=0;i<RTW_REPLAY_CTR_LEN; i++) */
  473. /* printk(" %02x ", psta->replay_ctr[i]); */
  474. }
  475. return _SUCCESS;
  476. }
  477. #endif /* CONFIG_GTK_OL */
  478. #ifdef CONFIG_RTW_MESH_AEK
  479. static int rtw_android_set_aek(struct net_device *ndev, char *command, int total_len)
  480. {
  481. #define SET_AEK_DATA_LEN (ETH_ALEN + 32)
  482. _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
  483. u8 *addr;
  484. u8 *aek;
  485. int err = 0;
  486. if (total_len - strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AEK]) - 1 != SET_AEK_DATA_LEN) {
  487. err = -EINVAL;
  488. goto exit;
  489. }
  490. addr = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AEK]) + 1;
  491. aek = addr + ETH_ALEN;
  492. RTW_PRINT(FUNC_NDEV_FMT" addr="MAC_FMT"\n"
  493. , FUNC_NDEV_ARG(ndev), MAC_ARG(addr));
  494. if (0)
  495. RTW_PRINT(FUNC_NDEV_FMT" aek="KEY_FMT KEY_FMT"\n"
  496. , FUNC_NDEV_ARG(ndev), KEY_ARG(aek), KEY_ARG(aek + 16));
  497. if (rtw_mesh_plink_set_aek(adapter, addr, aek) != _SUCCESS)
  498. err = -ENOENT;
  499. exit:
  500. return err;
  501. }
  502. #endif /* CONFIG_RTW_MESH_AEK */
  503. int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
  504. {
  505. #define PRIVATE_COMMAND_MAX_LEN 8192
  506. int ret = 0;
  507. char *command = NULL;
  508. int cmd_num;
  509. int bytes_written = 0;
  510. #ifdef CONFIG_PNO_SUPPORT
  511. uint cmdlen = 0;
  512. uint pno_enable = 0;
  513. #endif
  514. android_wifi_priv_cmd priv_cmd;
  515. _adapter *padapter = (_adapter *) rtw_netdev_priv(net);
  516. #ifdef CONFIG_WFD
  517. struct wifi_display_info *pwfd_info;
  518. #endif
  519. rtw_lock_suspend();
  520. if (!ifr->ifr_data) {
  521. ret = -EINVAL;
  522. goto exit;
  523. }
  524. if (padapter->registrypriv.mp_mode == 1) {
  525. ret = -EINVAL;
  526. goto exit;
  527. }
  528. #ifdef CONFIG_COMPAT
  529. #if (KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE)
  530. if (is_compat_task()) {
  531. #else
  532. if (in_compat_syscall()) {
  533. #endif
  534. /* User space is 32-bit, use compat ioctl */
  535. compat_android_wifi_priv_cmd compat_priv_cmd;
  536. if (copy_from_user(&compat_priv_cmd, ifr->ifr_data, sizeof(compat_android_wifi_priv_cmd))) {
  537. ret = -EFAULT;
  538. goto exit;
  539. }
  540. priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
  541. priv_cmd.used_len = compat_priv_cmd.used_len;
  542. priv_cmd.total_len = compat_priv_cmd.total_len;
  543. } else
  544. #endif /* CONFIG_COMPAT */
  545. if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
  546. ret = -EFAULT;
  547. goto exit;
  548. }
  549. if (padapter->registrypriv.mp_mode == 1) {
  550. ret = -EFAULT;
  551. goto exit;
  552. }
  553. /*RTW_INFO("%s priv_cmd.buf=%p priv_cmd.total_len=%d priv_cmd.used_len=%d\n",__func__,priv_cmd.buf,priv_cmd.total_len,priv_cmd.used_len);*/
  554. if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN || priv_cmd.total_len < 0) {
  555. RTW_WARN("%s: invalid private command (%d)\n", __FUNCTION__,
  556. priv_cmd.total_len);
  557. ret = -EFAULT;
  558. goto exit;
  559. }
  560. command = rtw_zmalloc(priv_cmd.total_len+1);
  561. if (!command) {
  562. RTW_INFO("%s: failed to allocate memory\n", __FUNCTION__);
  563. ret = -ENOMEM;
  564. goto exit;
  565. }
  566. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0))
  567. if (!access_ok(priv_cmd.buf, priv_cmd.total_len)) {
  568. #else
  569. if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)) {
  570. #endif
  571. RTW_INFO("%s: failed to access memory\n", __FUNCTION__);
  572. ret = -EFAULT;
  573. goto exit;
  574. }
  575. if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
  576. ret = -EFAULT;
  577. goto exit;
  578. }
  579. command[priv_cmd.total_len] = '\0';
  580. RTW_INFO("%s: Android private cmd \"%s\" on %s\n"
  581. , __FUNCTION__, command, ifr->ifr_name);
  582. cmd_num = rtw_android_cmdstr_to_num(command);
  583. switch (cmd_num) {
  584. case ANDROID_WIFI_CMD_START:
  585. /* bytes_written = wl_android_wifi_on(net); */
  586. goto response;
  587. case ANDROID_WIFI_CMD_SETFWPATH:
  588. goto response;
  589. }
  590. if (!g_wifi_on) {
  591. RTW_INFO("%s: Ignore private cmd \"%s\" - iface %s is down\n"
  592. , __FUNCTION__, command, ifr->ifr_name);
  593. ret = 0;
  594. goto exit;
  595. }
  596. if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST)) {
  597. switch (cmd_num) {
  598. case ANDROID_WIFI_CMD_WFD_ENABLE:
  599. case ANDROID_WIFI_CMD_WFD_DISABLE:
  600. case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
  601. case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
  602. case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
  603. goto response;
  604. }
  605. }
  606. switch (cmd_num) {
  607. case ANDROID_WIFI_CMD_STOP:
  608. /* bytes_written = wl_android_wifi_off(net); */
  609. break;
  610. case ANDROID_WIFI_CMD_SCAN_ACTIVE:
  611. /* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE); */
  612. #ifdef CONFIG_PLATFORM_MSTAR
  613. #ifdef CONFIG_IOCTL_CFG80211
  614. adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->bandroid_scan = _TRUE;
  615. #endif /* CONFIG_IOCTL_CFG80211 */
  616. #endif /* CONFIG_PLATFORM_MSTAR */
  617. break;
  618. case ANDROID_WIFI_CMD_SCAN_PASSIVE:
  619. /* rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE); */
  620. break;
  621. case ANDROID_WIFI_CMD_RSSI:
  622. bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
  623. break;
  624. case ANDROID_WIFI_CMD_LINKSPEED:
  625. bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
  626. break;
  627. case ANDROID_WIFI_CMD_MACADDR:
  628. bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
  629. break;
  630. case ANDROID_WIFI_CMD_BLOCK_SCAN:
  631. bytes_written = rtw_android_set_block_scan(net, command, priv_cmd.total_len);
  632. break;
  633. case ANDROID_WIFI_CMD_BLOCK:
  634. bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
  635. break;
  636. case ANDROID_WIFI_CMD_RXFILTER_START:
  637. /* bytes_written = net_os_set_packet_filter(net, 1); */
  638. break;
  639. case ANDROID_WIFI_CMD_RXFILTER_STOP:
  640. /* bytes_written = net_os_set_packet_filter(net, 0); */
  641. break;
  642. case ANDROID_WIFI_CMD_RXFILTER_ADD:
  643. /* int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; */
  644. /* bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); */
  645. break;
  646. case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
  647. /* int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; */
  648. /* bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); */
  649. break;
  650. case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
  651. /* TBD: BTCOEXSCAN-START */
  652. break;
  653. case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
  654. /* TBD: BTCOEXSCAN-STOP */
  655. break;
  656. case ANDROID_WIFI_CMD_BTCOEXMODE:
  657. #if 0
  658. uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
  659. if (mode == 1)
  660. net_os_set_packet_filter(net, 0); /* DHCP starts */
  661. else
  662. net_os_set_packet_filter(net, 1); /* DHCP ends */
  663. #ifdef WL_CFG80211
  664. bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
  665. #endif
  666. #endif
  667. break;
  668. case ANDROID_WIFI_CMD_SETSUSPENDOPT:
  669. /* bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); */
  670. break;
  671. case ANDROID_WIFI_CMD_SETBAND:
  672. bytes_written = rtw_android_setband(net, command, priv_cmd.total_len);
  673. break;
  674. case ANDROID_WIFI_CMD_GETBAND:
  675. bytes_written = rtw_android_getband(net, command, priv_cmd.total_len);
  676. break;
  677. case ANDROID_WIFI_CMD_COUNTRY:
  678. bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
  679. break;
  680. #ifdef CONFIG_PNO_SUPPORT
  681. case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
  682. /* bytes_written = dhd_dev_pno_reset(net); */
  683. break;
  684. case ANDROID_WIFI_CMD_PNOSETUP_SET:
  685. bytes_written = rtw_android_pno_setup(net, command, priv_cmd.total_len);
  686. break;
  687. case ANDROID_WIFI_CMD_PNOENABLE_SET:
  688. cmdlen = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_PNOENABLE_SET]);
  689. pno_enable = *(command + cmdlen + 1) - '0';
  690. bytes_written = rtw_android_pno_enable(net, pno_enable);
  691. break;
  692. #endif
  693. case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
  694. bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
  695. break;
  696. case ANDROID_WIFI_CMD_P2P_SET_NOA:
  697. /* int skip = strlen(CMD_P2P_SET_NOA) + 1; */
  698. /* bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); */
  699. break;
  700. case ANDROID_WIFI_CMD_P2P_GET_NOA:
  701. /* bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); */
  702. break;
  703. case ANDROID_WIFI_CMD_P2P_SET_PS:
  704. /* int skip = strlen(CMD_P2P_SET_PS) + 1; */
  705. /* bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); */
  706. break;
  707. #ifdef CONFIG_IOCTL_CFG80211
  708. case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE: {
  709. int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
  710. bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
  711. break;
  712. }
  713. #endif /* CONFIG_IOCTL_CFG80211 */
  714. #ifdef CONFIG_WFD
  715. case ANDROID_WIFI_CMD_MIRACAST:
  716. bytes_written = rtw_android_set_miracast_mode(net, command, priv_cmd.total_len);
  717. break;
  718. case ANDROID_WIFI_CMD_WFD_ENABLE: {
  719. /* Commented by Albert 2012/07/24 */
  720. /* We can enable the WFD function by using the following command: */
  721. /* wpa_cli driver wfd-enable */
  722. if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
  723. rtw_wfd_enable(padapter, 1);
  724. break;
  725. }
  726. case ANDROID_WIFI_CMD_WFD_DISABLE: {
  727. /* Commented by Albert 2012/07/24 */
  728. /* We can disable the WFD function by using the following command: */
  729. /* wpa_cli driver wfd-disable */
  730. if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
  731. rtw_wfd_enable(padapter, 0);
  732. break;
  733. }
  734. case ANDROID_WIFI_CMD_WFD_SET_TCPPORT: {
  735. /* Commented by Albert 2012/07/24 */
  736. /* We can set the tcp port number by using the following command: */
  737. /* wpa_cli driver wfd-set-tcpport = 554 */
  738. if (padapter->wdinfo.driver_interface == DRIVER_CFG80211)
  739. rtw_wfd_set_ctrl_port(padapter, (u16)get_int_from_command(command));
  740. break;
  741. }
  742. case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT: {
  743. break;
  744. }
  745. case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE: {
  746. /* Commented by Albert 2012/08/28 */
  747. /* Specify the WFD device type ( WFD source/primary sink ) */
  748. pwfd_info = &padapter->wfd_info;
  749. if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
  750. pwfd_info->wfd_device_type = (u8) get_int_from_command(command);
  751. pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
  752. }
  753. break;
  754. }
  755. #endif
  756. case ANDROID_WIFI_CMD_CHANGE_DTIM: {
  757. #ifdef CONFIG_LPS
  758. u8 dtim;
  759. u8 *ptr = (u8 *) command;
  760. ptr += 9;/* string command length of "SET_DTIM"; */
  761. dtim = rtw_atoi(ptr);
  762. RTW_INFO("DTIM=%d\n", dtim);
  763. rtw_lps_change_dtim_cmd(padapter, dtim);
  764. #endif
  765. }
  766. break;
  767. #if CONFIG_RTW_MACADDR_ACL
  768. case ANDROID_WIFI_CMD_HOSTAPD_SET_MACADDR_ACL: {
  769. rtw_set_macaddr_acl(padapter, RTW_ACL_PERIOD_BSS, get_int_from_command(command));
  770. break;
  771. }
  772. case ANDROID_WIFI_CMD_HOSTAPD_ACL_ADD_STA: {
  773. u8 addr[ETH_ALEN] = {0x00};
  774. macstr2num(addr, command + strlen("HOSTAPD_ACL_ADD_STA") + 3); /* 3 is space bar + "=" + space bar these 3 chars */
  775. rtw_acl_add_sta(padapter, RTW_ACL_PERIOD_BSS, addr);
  776. break;
  777. }
  778. case ANDROID_WIFI_CMD_HOSTAPD_ACL_REMOVE_STA: {
  779. u8 addr[ETH_ALEN] = {0x00};
  780. macstr2num(addr, command + strlen("HOSTAPD_ACL_REMOVE_STA") + 3); /* 3 is space bar + "=" + space bar these 3 chars */
  781. rtw_acl_remove_sta(padapter, RTW_ACL_PERIOD_BSS, addr);
  782. break;
  783. }
  784. #endif /* CONFIG_RTW_MACADDR_ACL */
  785. #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0))
  786. case ANDROID_WIFI_CMD_GTK_REKEY_OFFLOAD:
  787. rtw_gtk_offload(net, (u8 *)command);
  788. break;
  789. #endif /* CONFIG_GTK_OL */
  790. case ANDROID_WIFI_CMD_P2P_DISABLE: {
  791. #ifdef CONFIG_P2P
  792. rtw_p2p_enable(padapter, P2P_ROLE_DISABLE);
  793. #endif /* CONFIG_P2P */
  794. break;
  795. }
  796. #ifdef CONFIG_RTW_MESH_AEK
  797. case ANDROID_WIFI_CMD_SET_AEK:
  798. bytes_written = rtw_android_set_aek(net, command, priv_cmd.total_len);
  799. break;
  800. #endif
  801. case ANDROID_WIFI_CMD_DRIVERVERSION: {
  802. bytes_written = strlen(DRIVERVERSION);
  803. snprintf(command, bytes_written + 1, DRIVERVERSION);
  804. break;
  805. }
  806. default:
  807. RTW_INFO("Unknown PRIVATE command %s - ignored\n", command);
  808. snprintf(command, 3, "OK");
  809. bytes_written = strlen("OK");
  810. }
  811. response:
  812. if (bytes_written >= 0) {
  813. if ((bytes_written == 0) && (priv_cmd.total_len > 0))
  814. command[0] = '\0';
  815. if (bytes_written >= priv_cmd.total_len) {
  816. RTW_INFO("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
  817. bytes_written = priv_cmd.total_len;
  818. } else
  819. bytes_written++;
  820. priv_cmd.used_len = bytes_written;
  821. if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
  822. RTW_INFO("%s: failed to copy data to user buffer\n", __FUNCTION__);
  823. ret = -EFAULT;
  824. }
  825. } else
  826. ret = bytes_written;
  827. exit:
  828. rtw_unlock_suspend();
  829. if (command)
  830. rtw_mfree(command, priv_cmd.total_len);
  831. return ret;
  832. }
  833. /**
  834. * Functions for Android WiFi card detection
  835. */
  836. #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
  837. static int g_wifidev_registered = 0;
  838. static struct semaphore wifi_control_sem;
  839. static struct wifi_platform_data *wifi_control_data = NULL;
  840. static struct resource *wifi_irqres = NULL;
  841. static int wifi_add_dev(void);
  842. static void wifi_del_dev(void);
  843. int rtw_android_wifictrl_func_add(void)
  844. {
  845. int ret = 0;
  846. sema_init(&wifi_control_sem, 0);
  847. ret = wifi_add_dev();
  848. if (ret) {
  849. RTW_INFO("%s: platform_driver_register failed\n", __FUNCTION__);
  850. return ret;
  851. }
  852. g_wifidev_registered = 1;
  853. /* Waiting callback after platform_driver_register is done or exit with error */
  854. if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
  855. ret = -EINVAL;
  856. RTW_INFO("%s: platform_driver_register timeout\n", __FUNCTION__);
  857. }
  858. return ret;
  859. }
  860. void rtw_android_wifictrl_func_del(void)
  861. {
  862. if (g_wifidev_registered) {
  863. wifi_del_dev();
  864. g_wifidev_registered = 0;
  865. }
  866. }
  867. void *wl_android_prealloc(int section, unsigned long size)
  868. {
  869. void *alloc_ptr = NULL;
  870. if (wifi_control_data && wifi_control_data->mem_prealloc) {
  871. alloc_ptr = wifi_control_data->mem_prealloc(section, size);
  872. if (alloc_ptr) {
  873. RTW_INFO("success alloc section %d\n", section);
  874. if (size != 0L)
  875. memset(alloc_ptr, 0, size);
  876. return alloc_ptr;
  877. }
  878. }
  879. RTW_INFO("can't alloc section %d\n", section);
  880. return NULL;
  881. }
  882. int wifi_get_irq_number(unsigned long *irq_flags_ptr)
  883. {
  884. if (wifi_irqres) {
  885. *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
  886. return (int)wifi_irqres->start;
  887. }
  888. #ifdef CUSTOM_OOB_GPIO_NUM
  889. return CUSTOM_OOB_GPIO_NUM;
  890. #else
  891. return -1;
  892. #endif
  893. }
  894. int wifi_set_power(int on, unsigned long msec)
  895. {
  896. RTW_INFO("%s = %d\n", __FUNCTION__, on);
  897. if (wifi_control_data && wifi_control_data->set_power)
  898. wifi_control_data->set_power(on);
  899. if (msec)
  900. msleep(msec);
  901. return 0;
  902. }
  903. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
  904. int wifi_get_mac_addr(unsigned char *buf)
  905. {
  906. RTW_INFO("%s\n", __FUNCTION__);
  907. if (!buf)
  908. return -EINVAL;
  909. if (wifi_control_data && wifi_control_data->get_mac_addr)
  910. return wifi_control_data->get_mac_addr(buf);
  911. return -EOPNOTSUPP;
  912. }
  913. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
  914. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
  915. void *wifi_get_country_code(char *ccode)
  916. {
  917. RTW_INFO("%s\n", __FUNCTION__);
  918. if (!ccode)
  919. return NULL;
  920. if (wifi_control_data && wifi_control_data->get_country_code)
  921. return wifi_control_data->get_country_code(ccode);
  922. return NULL;
  923. }
  924. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
  925. static int wifi_set_carddetect(int on)
  926. {
  927. RTW_INFO("%s = %d\n", __FUNCTION__, on);
  928. if (wifi_control_data && wifi_control_data->set_carddetect)
  929. wifi_control_data->set_carddetect(on);
  930. return 0;
  931. }
  932. static int wifi_probe(struct platform_device *pdev)
  933. {
  934. struct wifi_platform_data *wifi_ctrl =
  935. (struct wifi_platform_data *)(pdev->dev.platform_data);
  936. int wifi_wake_gpio = 0;
  937. RTW_INFO("## %s\n", __FUNCTION__);
  938. wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
  939. if (wifi_irqres == NULL)
  940. wifi_irqres = platform_get_resource_byname(pdev,
  941. IORESOURCE_IRQ, "bcm4329_wlan_irq");
  942. else
  943. wifi_wake_gpio = wifi_irqres->start;
  944. #ifdef CONFIG_GPIO_WAKEUP
  945. RTW_INFO("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
  946. (int)wifi_irqres->start, wifi_wake_gpio);
  947. if (wifi_wake_gpio > 0) {
  948. #ifdef CONFIG_PLATFORM_INTEL_BYT
  949. wifi_configure_gpio();
  950. #else /* CONFIG_PLATFORM_INTEL_BYT */
  951. gpio_request(wifi_wake_gpio, "oob_irq");
  952. gpio_direction_input(wifi_wake_gpio);
  953. oob_irq = gpio_to_irq(wifi_wake_gpio);
  954. #endif /* CONFIG_PLATFORM_INTEL_BYT */
  955. RTW_INFO("%s oob_irq:%d\n", __func__, oob_irq);
  956. } else if (wifi_irqres) {
  957. oob_irq = wifi_irqres->start;
  958. RTW_INFO("%s oob_irq:%d\n", __func__, oob_irq);
  959. }
  960. #endif
  961. wifi_control_data = wifi_ctrl;
  962. wifi_set_power(1, 0); /* Power On */
  963. wifi_set_carddetect(1); /* CardDetect (0->1) */
  964. up(&wifi_control_sem);
  965. return 0;
  966. }
  967. #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
  968. extern PADAPTER g_test_adapter;
  969. static void shutdown_card(void)
  970. {
  971. u32 addr;
  972. u8 tmp8, cnt = 0;
  973. if (NULL == g_test_adapter) {
  974. RTW_INFO("%s: padapter==NULL\n", __FUNCTION__);
  975. return;
  976. }
  977. #ifdef CONFIG_FWLPS_IN_IPS
  978. LeaveAllPowerSaveMode(g_test_adapter);
  979. #endif /* CONFIG_FWLPS_IN_IPS */
  980. #ifdef CONFIG_WOWLAN
  981. #ifdef CONFIG_GPIO_WAKEUP
  982. /*default wake up pin change to BT*/
  983. RTW_INFO("%s:default wake up pin change to BT\n", __FUNCTION__);
  984. rtw_hal_switch_gpio_wl_ctrl(g_test_adapter, WAKEUP_GPIO_IDX, _FALSE);
  985. #endif /* CONFIG_GPIO_WAKEUP */
  986. #endif /* CONFIG_WOWLAN */
  987. /* Leave SDIO HCI Suspend */
  988. addr = 0x10250086;
  989. rtw_write8(g_test_adapter, addr, 0);
  990. do {
  991. tmp8 = rtw_read8(g_test_adapter, addr);
  992. cnt++;
  993. RTW_INFO(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n",
  994. FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt);
  995. if (tmp8 & BIT(1))
  996. break;
  997. if (cnt >= 100) {
  998. RTW_INFO(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n",
  999. FUNC_ADPT_ARG(g_test_adapter), addr);
  1000. break;
  1001. }
  1002. rtw_mdelay_os(10);
  1003. } while (1);
  1004. /* unlock register I/O */
  1005. rtw_write8(g_test_adapter, 0x1C, 0);
  1006. /* enable power down function */
  1007. /* 0x04[4] = 1 */
  1008. /* 0x05[7] = 1 */
  1009. addr = 0x04;
  1010. tmp8 = rtw_read8(g_test_adapter, addr);
  1011. tmp8 |= BIT(4);
  1012. rtw_write8(g_test_adapter, addr, tmp8);
  1013. RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
  1014. FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
  1015. addr = 0x05;
  1016. tmp8 = rtw_read8(g_test_adapter, addr);
  1017. tmp8 |= BIT(7);
  1018. rtw_write8(g_test_adapter, addr, tmp8);
  1019. RTW_INFO(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n",
  1020. FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr));
  1021. /* lock register page0 0x0~0xB read/write */
  1022. rtw_write8(g_test_adapter, 0x1C, 0x0E);
  1023. rtw_set_surprise_removed(g_test_adapter);
  1024. RTW_INFO(FUNC_ADPT_FMT ": bSurpriseRemoved=%s\n",
  1025. FUNC_ADPT_ARG(g_test_adapter), rtw_is_surprise_removed(g_test_adapter) ? "True" : "False");
  1026. }
  1027. #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
  1028. static int wifi_remove(struct platform_device *pdev)
  1029. {
  1030. struct wifi_platform_data *wifi_ctrl =
  1031. (struct wifi_platform_data *)(pdev->dev.platform_data);
  1032. RTW_INFO("## %s\n", __FUNCTION__);
  1033. wifi_control_data = wifi_ctrl;
  1034. wifi_set_power(0, 0); /* Power Off */
  1035. wifi_set_carddetect(0); /* CardDetect (1->0) */
  1036. up(&wifi_control_sem);
  1037. return 0;
  1038. }
  1039. #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
  1040. static void wifi_shutdown(struct platform_device *pdev)
  1041. {
  1042. struct wifi_platform_data *wifi_ctrl =
  1043. (struct wifi_platform_data *)(pdev->dev.platform_data);
  1044. RTW_INFO("## %s\n", __FUNCTION__);
  1045. wifi_control_data = wifi_ctrl;
  1046. shutdown_card();
  1047. wifi_set_power(0, 0); /* Power Off */
  1048. wifi_set_carddetect(0); /* CardDetect (1->0) */
  1049. }
  1050. #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
  1051. static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
  1052. {
  1053. RTW_INFO("##> %s\n", __FUNCTION__);
  1054. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
  1055. bcmsdh_oob_intr_set(0);
  1056. #endif
  1057. return 0;
  1058. }
  1059. static int wifi_resume(struct platform_device *pdev)
  1060. {
  1061. RTW_INFO("##> %s\n", __FUNCTION__);
  1062. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
  1063. if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
  1064. bcmsdh_oob_intr_set(1);
  1065. #endif
  1066. return 0;
  1067. }
  1068. /* temporarily use these two */
  1069. static struct platform_driver wifi_device = {
  1070. .probe = wifi_probe,
  1071. .remove = wifi_remove,
  1072. .suspend = wifi_suspend,
  1073. .resume = wifi_resume,
  1074. #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
  1075. .shutdown = wifi_shutdown,
  1076. #endif /* RTW_SUPPORT_PLATFORM_SHUTDOWN */
  1077. .driver = {
  1078. .name = "bcmdhd_wlan",
  1079. }
  1080. };
  1081. static struct platform_driver wifi_device_legacy = {
  1082. .probe = wifi_probe,
  1083. .remove = wifi_remove,
  1084. .suspend = wifi_suspend,
  1085. .resume = wifi_resume,
  1086. .driver = {
  1087. .name = "bcm4329_wlan",
  1088. }
  1089. };
  1090. static int wifi_add_dev(void)
  1091. {
  1092. RTW_INFO("## Calling platform_driver_register\n");
  1093. platform_driver_register(&wifi_device);
  1094. platform_driver_register(&wifi_device_legacy);
  1095. return 0;
  1096. }
  1097. static void wifi_del_dev(void)
  1098. {
  1099. RTW_INFO("## Unregister platform_driver_register\n");
  1100. platform_driver_unregister(&wifi_device);
  1101. platform_driver_unregister(&wifi_device_legacy);
  1102. }
  1103. #endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
  1104. #ifdef CONFIG_GPIO_WAKEUP
  1105. #ifdef CONFIG_PLATFORM_INTEL_BYT
  1106. int wifi_configure_gpio(void)
  1107. {
  1108. if (gpio_request(oob_gpio, "oob_irq")) {
  1109. RTW_INFO("## %s Cannot request GPIO\n", __FUNCTION__);
  1110. return -1;
  1111. }
  1112. gpio_export(oob_gpio, 0);
  1113. if (gpio_direction_input(oob_gpio)) {
  1114. RTW_INFO("## %s Cannot set GPIO direction input\n", __FUNCTION__);
  1115. return -1;
  1116. }
  1117. oob_irq = gpio_to_irq(oob_gpio);
  1118. if (oob_irq < 0) {
  1119. RTW_INFO("## %s Cannot convert GPIO to IRQ\n", __FUNCTION__);
  1120. return -1;
  1121. }
  1122. RTW_INFO("## %s OOB_IRQ=%d\n", __FUNCTION__, oob_irq);
  1123. return 0;
  1124. }
  1125. #endif /* CONFIG_PLATFORM_INTEL_BYT */
  1126. void wifi_free_gpio(unsigned int gpio)
  1127. {
  1128. #ifdef CONFIG_PLATFORM_INTEL_BYT
  1129. if (gpio)
  1130. gpio_free(gpio);
  1131. #endif /* CONFIG_PLATFORM_INTEL_BYT */
  1132. }
  1133. #endif /* CONFIG_GPIO_WAKEUP */