int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { int ret = 0; char *command = NULL; int bytes_written = 0; android_wifi_priv_cmd priv_cmd; net_os_wake_lock(net); if (!ifr->ifr_data) { ret = -EINVAL; goto exit; } if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ret = -EFAULT; goto exit; } command = kmalloc(priv_cmd.total_len, GFP_KERNEL); if (!command) { DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); ret = -ENOMEM; goto exit; } if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ret = -EFAULT; goto exit; } DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) { DHD_INFO(("%s, Received regular START command\n", __FUNCTION__)); bytes_written = wl_android_wifi_on(net); } else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) { bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len); } if (!g_wifi_on) { DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n", __FUNCTION__, command, ifr->ifr_name)); ret = 0; goto exit; } if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) { bytes_written = wl_android_wifi_off(net); } else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) { /* TBD: SCAN-ACTIVE */ } else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) { /* TBD: SCAN-PASSIVE */ } else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) { bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_P2P_HANG, strlen(CMD_P2P_HANG)) == 0) { printk(KERN_ERR "WL: Make an hang for reset test\n"); bytes_written = net_os_send_hang_message(net); } else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) { bytes_written = net_os_set_packet_filter(net, 1); } else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) { bytes_written = net_os_set_packet_filter(net, 0); } else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) { int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); } else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) { int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); } else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) { /* TBD: BTCOEXSCAN-START */ } else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) { /* TBD: BTCOEXSCAN-STOP */ } else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) { uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0'; if (mode == 1) net_os_set_packet_filter(net, 0); /* DHCP starts */ else net_os_set_packet_filter(net, 1); /* DHCP ends */ #ifdef WL_CFG80211 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command); #endif } else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; bytes_written = wldev_set_band(net, band); } else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { char *country_code = command + strlen(CMD_COUNTRY) + 1; bytes_written = wldev_set_country(net, country_code); #ifdef WL_CFG80211 wl_update_wiphybands(NULL); #endif } #if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { bytes_written = dhd_dev_pno_reset(net); } else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; bytes_written = dhd_dev_pno_enable(net, pfn_enabled); } #endif else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) { bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) { int skip = strlen(CMD_P2P_SET_NOA) + 1; bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); } #if !defined WL_ENABLE_P2P_IF else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); } #endif else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { int skip = strlen(CMD_P2P_SET_PS) + 1; bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); } #ifdef WL_CFG80211 else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) { int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3; bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0'); } #endif /* WL_CFG80211 */ else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); bytes_written = strlen("OK"); } if (bytes_written >= 0) { if ((bytes_written == 0) && (priv_cmd.total_len > 0)) command[0] = '\0'; if (bytes_written >= priv_cmd.total_len) { DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); bytes_written = priv_cmd.total_len; } else { bytes_written++; } priv_cmd.used_len = bytes_written; if (copy_to_user(priv_cmd.buf, command, bytes_written)) { DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); ret = -EFAULT; } } else { ret = bytes_written; } exit: net_os_wake_unlock(net); if (command) { kfree(command); } return ret; }
int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { #define PRIVATE_COMMAND_MAX_LEN 8192 int ret = 0; char *command = NULL; int bytes_written = 0; android_wifi_priv_cmd priv_cmd; net_os_wake_lock(net); if (!ifr->ifr_data) { ret = -EINVAL; goto exit; } if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) { ret = -EFAULT; goto exit; } if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) { DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__)); ret = -EINVAL; } command = kmalloc(priv_cmd.total_len, GFP_KERNEL); if (!command) { DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); ret = -ENOMEM; goto exit; } if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) { ret = -EFAULT; goto exit; } DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) { DHD_INFO(("%s, Received regular START command\n", __FUNCTION__)); bytes_written = wl_android_wifi_on(net); } else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) { bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len); } if (!g_wifi_on) { DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n", __FUNCTION__, command, ifr->ifr_name)); ret = 0; goto exit; } if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) { bytes_written = wl_android_wifi_off(net); } else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) { /* TBD: SCAN-ACTIVE */ } else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) { /* TBD: SCAN-PASSIVE */ } else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) { bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len); } #ifdef PKT_FILTER_SUPPORT else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) { bytes_written = net_os_enable_packet_filter(net, 1); } else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) { bytes_written = net_os_enable_packet_filter(net, 0); } else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) { int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); } else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) { int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); } #endif /* PKT_FILTER_SUPPORT */ else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) { /* TBD: BTCOEXSCAN-START */ } else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) { /* TBD: BTCOEXSCAN-STOP */ } else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) { #ifdef WL_CFG80211 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command); #else #ifdef PKT_FILTER_SUPPORT uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0'; if (mode == 1) net_os_enable_packet_filter(net, 0); /* DHCP starts */ else net_os_enable_packet_filter(net, 1); /* DHCP ends */ #endif /* PKT_FILTER_SUPPORT */ #endif /* WL_CFG80211 */ } else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; #ifdef WL_HOST_BAND_MGMT if (wl_cfg80211_set_band(net, band) < 0) { bytes_written = -1; goto exit; } if (band == WLC_BAND_AUTO) bytes_written = wldev_set_band(net, band); #else bytes_written = wldev_set_band(net, band); #endif /* WL_HOST_BAND_MGMT */ } else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); } #ifdef WL_CFG80211 /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */ else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { char *country_code = command + strlen(CMD_COUNTRY) + 1; bytes_written = wldev_set_country(net, country_code, true, true); } #endif /* WL_CFG80211 */ #if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { bytes_written = dhd_dev_pno_reset(net); } else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; bytes_written = dhd_dev_pno_enable(net, pfn_enabled); } #endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) { bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) { int skip = strlen(CMD_P2P_SET_NOA) + 1; bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); } #ifdef WL_SDO else if (strnicmp(command, CMD_P2P_SD_OFFLOAD, strlen(CMD_P2P_SD_OFFLOAD)) == 0) { u8 *buf = command; u8 *cmd_id = NULL; int len; cmd_id = strsep((char **)&buf, " "); /* if buf == NULL, means no arg */ if (buf == NULL) len = 0; else len = strlen(buf); bytes_written = wl_cfg80211_sd_offload(net, cmd_id, buf, len); } #endif /* WL_SDO */ #if !defined WL_ENABLE_P2P_IF else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); } #endif /* WL_ENABLE_P2P_IF */ else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { int skip = strlen(CMD_P2P_SET_PS) + 1; bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip); } #ifdef WL_CFG80211 else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) { int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3; bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0'); } #endif /* WL_CFG80211 */ #if defined(WL_SUPPORT_AUTO_CHANNEL) else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL, strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) { int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 3; bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_GET_BEST_CHANNELS, strlen(CMD_GET_BEST_CHANNELS)) == 0) { bytes_written = wl_cfg80211_get_best_channels(net, command, priv_cmd.total_len); } #endif /* WL_SUPPORT_AUTO_CHANNEL */ #if defined(SUPPORT_TRIGGER_HANG_EVENT) else if (strnicmp(command, CMD_TEST_FORCE_HANG, strlen(CMD_TEST_FORCE_HANG)) == 0) { net_os_send_hang_message(net); } #endif /* SUPPORT_TRIGGER_HANG_EVENT */ else if (strnicmp(command, CMD_SETMIRACAST, strlen(CMD_SETMIRACAST)) == 0) { bytes_written = wldev_miracast_tuning(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_ASSOCRESPIE, strlen(CMD_ASSOCRESPIE)) == 0) bytes_written = wldev_get_assoc_resp_ie(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_MAXLINKSPEED, strlen(CMD_MAXLINKSPEED)) == 0) bytes_written = wldev_get_max_linkspeed(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len); else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len); else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); bytes_written = strlen("OK"); } if (bytes_written >= 0) { if ((bytes_written == 0) && (priv_cmd.total_len > 0)) command[0] = '\0'; if (bytes_written >= priv_cmd.total_len) { DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); bytes_written = priv_cmd.total_len; } else { bytes_written++; } priv_cmd.used_len = bytes_written; if (copy_to_user(priv_cmd.buf, command, bytes_written)) { DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); ret = -EFAULT; } } else { ret = bytes_written; } exit: net_os_wake_unlock(net); if (command) { kfree(command); } return ret; }