rtw_android.c 33 KB

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