rtw_android.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. #include <linux/module.h>
  21. #include <linux/netdevice.h>
  22. #include <rtw_android.h>
  23. #include <osdep_service.h>
  24. #include <rtw_debug.h>
  25. #include <rtw_ioctl_set.h>
  26. static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
  27. "START",
  28. "STOP",
  29. "SCAN-ACTIVE",
  30. "SCAN-PASSIVE",
  31. "RSSI",
  32. "LINKSPEED",
  33. "RXFILTER-START",
  34. "RXFILTER-STOP",
  35. "RXFILTER-ADD",
  36. "RXFILTER-REMOVE",
  37. "BTCOEXSCAN-START",
  38. "BTCOEXSCAN-STOP",
  39. "BTCOEXMODE",
  40. "SETSUSPENDOPT",
  41. "P2P_DEV_ADDR",
  42. "SETFWPATH",
  43. "SETBAND",
  44. "GETBAND",
  45. "COUNTRY",
  46. "P2P_SET_NOA",
  47. "P2P_GET_NOA",
  48. "P2P_SET_PS",
  49. "SET_AP_WPS_P2P_IE",
  50. "MACADDR",
  51. "BLOCK",
  52. "WFD-ENABLE",
  53. "WFD-DISABLE",
  54. "WFD-SET-TCPPORT",
  55. "WFD-SET-MAXTPUT",
  56. "WFD-SET-DEVTYPE",
  57. };
  58. struct android_wifi_priv_cmd {
  59. const char __user *buf;
  60. int used_len;
  61. int total_len;
  62. };
  63. /**
  64. * Local (static) functions and variables
  65. */
  66. /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
  67. * time (only) in dhd_open, subsequential wifi on will be handled by
  68. * wl_android_wifi_on
  69. */
  70. static int g_wifi_on = true;
  71. int rtw_android_cmdstr_to_num(char *cmdstr)
  72. {
  73. int cmd_num;
  74. for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
  75. if (0 == strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
  76. strlen(android_wifi_cmd_str[cmd_num])))
  77. break;
  78. return cmd_num;
  79. }
  80. static int rtw_android_get_rssi(struct net_device *net, char *command,
  81. int total_len)
  82. {
  83. struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
  84. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  85. struct wlan_network *pcur_network = &pmlmepriv->cur_network;
  86. int bytes_written = 0;
  87. if (check_fwstate(pmlmepriv, _FW_LINKED)) {
  88. bytes_written += snprintf(&command[bytes_written], total_len,
  89. "%s rssi %d",
  90. pcur_network->network.Ssid.Ssid,
  91. padapter->recvpriv.rssi);
  92. }
  93. return bytes_written;
  94. }
  95. static int rtw_android_get_link_speed(struct net_device *net, char *command,
  96. int total_len)
  97. {
  98. struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
  99. u16 link_speed;
  100. link_speed = rtw_get_cur_max_rate(padapter) / 10;
  101. return snprintf(command, total_len, "LinkSpeed %d",
  102. link_speed);
  103. }
  104. static int rtw_android_get_macaddr(struct net_device *net, char *command,
  105. int total_len)
  106. {
  107. return snprintf(command, total_len, "Macaddr = %pM",
  108. net->dev_addr);
  109. }
  110. static int android_set_cntry(struct net_device *net, char *command,
  111. int total_len)
  112. {
  113. struct adapter *adapter = (struct adapter *)rtw_netdev_priv(net);
  114. char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
  115. int ret;
  116. ret = rtw_set_country(adapter, country_code);
  117. return (ret == _SUCCESS) ? 0 : -1;
  118. }
  119. static int android_get_p2p_addr(struct net_device *net, char *command,
  120. int total_len)
  121. {
  122. /* We use the same address as our HW MAC address */
  123. memcpy(command, net->dev_addr, ETH_ALEN);
  124. return ETH_ALEN;
  125. }
  126. static int rtw_android_set_block(struct net_device *net, char *command,
  127. int total_len)
  128. {
  129. return 0;
  130. }
  131. int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
  132. {
  133. int ret = 0;
  134. char *command;
  135. int cmd_num;
  136. int bytes_written = 0;
  137. struct android_wifi_priv_cmd priv_cmd;
  138. if (!ifr->ifr_data)
  139. return -EINVAL;
  140. if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(priv_cmd)))
  141. return -EFAULT;
  142. if (priv_cmd.total_len < 1)
  143. return -EINVAL;
  144. command = memdup_user(priv_cmd.buf, priv_cmd.total_len);
  145. if (IS_ERR(command))
  146. return PTR_ERR(command);
  147. command[priv_cmd.total_len - 1] = 0;
  148. DBG_88E("%s: Android private cmd \"%s\" on %s\n",
  149. __func__, command, ifr->ifr_name);
  150. cmd_num = rtw_android_cmdstr_to_num(command);
  151. switch (cmd_num) {
  152. case ANDROID_WIFI_CMD_START:
  153. goto response;
  154. case ANDROID_WIFI_CMD_SETFWPATH:
  155. goto response;
  156. }
  157. if (!g_wifi_on) {
  158. DBG_88E("%s: Ignore private cmd \"%s\" - iface %s is down\n",
  159. __func__, command, ifr->ifr_name);
  160. ret = 0;
  161. goto free;
  162. }
  163. switch (cmd_num) {
  164. case ANDROID_WIFI_CMD_STOP:
  165. break;
  166. case ANDROID_WIFI_CMD_SCAN_ACTIVE:
  167. break;
  168. case ANDROID_WIFI_CMD_SCAN_PASSIVE:
  169. break;
  170. case ANDROID_WIFI_CMD_RSSI:
  171. bytes_written = rtw_android_get_rssi(net, command,
  172. priv_cmd.total_len);
  173. break;
  174. case ANDROID_WIFI_CMD_LINKSPEED:
  175. bytes_written = rtw_android_get_link_speed(net, command,
  176. priv_cmd.total_len);
  177. break;
  178. case ANDROID_WIFI_CMD_MACADDR:
  179. bytes_written = rtw_android_get_macaddr(net, command,
  180. priv_cmd.total_len);
  181. break;
  182. case ANDROID_WIFI_CMD_BLOCK:
  183. bytes_written = rtw_android_set_block(net, command,
  184. priv_cmd.total_len);
  185. break;
  186. case ANDROID_WIFI_CMD_RXFILTER_START:
  187. break;
  188. case ANDROID_WIFI_CMD_RXFILTER_STOP:
  189. break;
  190. case ANDROID_WIFI_CMD_RXFILTER_ADD:
  191. break;
  192. case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
  193. break;
  194. case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
  195. /* TBD: BTCOEXSCAN-START */
  196. break;
  197. case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
  198. /* TBD: BTCOEXSCAN-STOP */
  199. break;
  200. case ANDROID_WIFI_CMD_BTCOEXMODE:
  201. break;
  202. case ANDROID_WIFI_CMD_SETSUSPENDOPT:
  203. break;
  204. case ANDROID_WIFI_CMD_SETBAND:
  205. break;
  206. case ANDROID_WIFI_CMD_GETBAND:
  207. break;
  208. case ANDROID_WIFI_CMD_COUNTRY:
  209. bytes_written = android_set_cntry(net, command,
  210. priv_cmd.total_len);
  211. break;
  212. case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
  213. bytes_written = android_get_p2p_addr(net, command,
  214. priv_cmd.total_len);
  215. break;
  216. case ANDROID_WIFI_CMD_P2P_SET_NOA:
  217. break;
  218. case ANDROID_WIFI_CMD_P2P_GET_NOA:
  219. break;
  220. case ANDROID_WIFI_CMD_P2P_SET_PS:
  221. break;
  222. default:
  223. DBG_88E("Unknown PRIVATE command %s - ignored\n", command);
  224. snprintf(command, 3, "OK");
  225. bytes_written = strlen("OK");
  226. }
  227. response:
  228. if (bytes_written >= 0) {
  229. if ((bytes_written == 0) && (priv_cmd.total_len > 0))
  230. command[0] = '\0';
  231. if (bytes_written >= priv_cmd.total_len) {
  232. DBG_88E("%s: bytes_written = %d\n", __func__,
  233. bytes_written);
  234. bytes_written = priv_cmd.total_len;
  235. } else {
  236. bytes_written++;
  237. }
  238. priv_cmd.used_len = bytes_written;
  239. if (copy_to_user((char __user *)priv_cmd.buf, command,
  240. bytes_written)) {
  241. DBG_88E("%s: failed to copy data to user buffer\n",
  242. __func__);
  243. ret = -EFAULT;
  244. }
  245. } else {
  246. ret = bytes_written;
  247. }
  248. free:
  249. kfree(command);
  250. return ret;
  251. }