driver_cmd_nl80211.c revision b05da5a8c808715098cae93ef1db1f2684f71c9f
1b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt/* 2b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * Driver interaction with extended Linux CFG8021 3b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * 4b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 5b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 6b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * published by the Free Software Foundation. 7b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * 8b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 9b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * license. 10b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt * 11b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt */ 12b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 13b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt#include "driver_nl80211.h" 14991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt#include "driver_cmd_common.h" 15b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 16991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt#include "wpa_supplicant_i.h" 17991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt#include "config.h" 18991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 19991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt#define WPA_EVENT_DRIVER_STATE "CTRL-EVENT-DRIVER-STATE " 20b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 21b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt#define WPA_PS_ENABLED 0 22b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt#define WPA_PS_DISABLED 1 23b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 24d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidttypedef struct android_wifi_priv_cmd { 25d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt char *buf; 26d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt int used_len; 27d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt int total_len; 28d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt} android_wifi_priv_cmd; 29d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 30b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtint send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, 31b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int (*valid_handler)(struct nl_msg *, void *), 32b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt void *valid_data); 33b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 34991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic int drv_errors = 0; 35991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 36991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) 37991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt{ 38991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors++; 39991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 40991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 41991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 42991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 43991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt} 44991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 45b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtstatic int wpa_driver_set_power_save(void *priv, int state) 46b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 47b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 48b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 49b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct nl_msg *msg; 50b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = -1; 51b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt enum nl80211_ps_state ps_state; 52b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 53b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = nlmsg_alloc(); 54b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!msg) 55b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return -1; 56b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 57b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 58b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NL80211_CMD_SET_POWER_SAVE, 0); 59b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 60b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (state == WPA_PS_ENABLED) 61b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ps_state = NL80211_PS_ENABLED; 62b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt else 63b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ps_state = NL80211_PS_DISABLED; 64b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 65b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 66b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); 67b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 68b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 69b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = NULL; 70b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (ret < 0) 71b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Set power mode fail: %d", ret); 72b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtnla_put_failure: 73b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt nlmsg_free(msg); 74b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 75b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 76b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 77b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtstatic int get_power_mode_handler(struct nl_msg *msg, void *arg) 78b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 79b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 80b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 81b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int *state = (int *)arg; 82b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 83b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 84b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 85b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 86b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!tb[NL80211_ATTR_PS_STATE]) 87b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return NL_SKIP; 88b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 89b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (state) { 90b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt *state = (int)nla_get_u32(tb[NL80211_ATTR_PS_STATE]); 91b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Get power mode = %d", *state); 92b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt *state = (*state == NL80211_PS_ENABLED) ? 93b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt WPA_PS_ENABLED : WPA_PS_DISABLED; 94b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } 95b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 96b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return NL_SKIP; 97b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 98b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 99b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtstatic int wpa_driver_get_power_save(void *priv, int *state) 100b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 101b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 102b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 103b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct nl_msg *msg; 104b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = -1; 105b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt enum nl80211_ps_state ps_state; 106b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 107b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = nlmsg_alloc(); 108b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!msg) 109b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return -1; 110b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 111b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 112b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NL80211_CMD_GET_POWER_SAVE, 0); 113b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 114b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 115b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 116b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, get_power_mode_handler, state); 117b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt msg = NULL; 118b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (ret < 0) 119b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Get power mode fail: %d", ret); 120b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtnla_put_failure: 121b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt nlmsg_free(msg); 122b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 123b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 124b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 125991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidtstatic int wpa_driver_set_backgroundscan_params(void *priv) 126991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt{ 127991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct i802_bss *bss = priv; 128991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 129991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct wpa_supplicant *wpa_s; 130991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct ifreq ifr; 131991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt android_wifi_priv_cmd priv_cmd; 132991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt int ret = 0, i = 0, bp; 133991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt char buf[WEXT_PNO_MAX_COMMAND_SIZE]; 134991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt struct wpa_ssid *ssid_conf; 135991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 136991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv == NULL) { 137991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__); 138991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return -1; 139991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 140991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (drv->ctx == NULL) { 141991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__); 142991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return -1; 143991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 144991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_s = (struct wpa_supplicant *)(drv->ctx); 145991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (wpa_s->conf == NULL) { 146991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__); 147991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return -1; 148991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 149991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ssid_conf = wpa_s->conf->ssid; 150991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 151991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp = WEXT_PNOSETUP_HEADER_SIZE; 152991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); 153991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_PREFIX; 154991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_VERSION; 155991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_SUBVERSION; 156991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_TLV_RESERVED; 157991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 158991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt while ((i < WEXT_PNO_AMOUNT) && (ssid_conf != NULL)) { 159991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt /* Check that there is enough space needed for 1 more SSID, the other sections and null termination */ 160991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int)sizeof(buf)) 161991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt break; 162991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if ((!ssid_conf->disabled) && (ssid_conf->ssid_len <= MAX_SSID_LEN)){ 163991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_DEBUG, "For PNO Scan: %s", ssid_conf->ssid); 164991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_SSID_SECTION; 165991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = ssid_conf->ssid_len; 166991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(&buf[bp], ssid_conf->ssid, ssid_conf->ssid_len); 167991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += ssid_conf->ssid_len; 168991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt i++; 169991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 170991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ssid_conf = ssid_conf->next; 171991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 172991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 173991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; 174991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", WEXT_PNO_SCAN_INTERVAL); 175991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; 176991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 177991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_REPEAT_SECTION; 178991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", WEXT_PNO_REPEAT); 179991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += WEXT_PNO_REPEAT_LENGTH; 180991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 181991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; 182991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", WEXT_PNO_MAX_REPEAT); 183991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; 184991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 185991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 186991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt memset(&priv_cmd, 0, sizeof(priv_cmd)); 187991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 188991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 189991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt priv_cmd.buf = buf; 190991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt priv_cmd.used_len = bp; 191991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt priv_cmd.total_len = bp; 192991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ifr.ifr_data = &priv_cmd; 193991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 194991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); 195991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 196991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (ret < 0) { 197991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", ret); 198991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 199991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 200991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 201991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 202991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return ret; 203991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt} 204991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt 205b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidtint wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, 206b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt size_t buf_len ) 207b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt{ 208b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct i802_bss *bss = priv; 209b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 210d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt struct ifreq ifr; 211d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt android_wifi_priv_cmd priv_cmd; 212b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int ret = 0; 213b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 214b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (os_strcasecmp(cmd, "STOP") == 0) { 215b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0); 216b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); 217b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "START") == 0) { 218b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1); 219b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); 220b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "MACADDR") == 0) { 221b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt u8 macaddr[ETH_ALEN] = {}; 222b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 223b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, macaddr); 224b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt if (!ret) 225b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = os_snprintf(buf, buf_len, 226b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); 227b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strcasecmp(cmd, "RELOAD") == 0) { 228b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 229b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) { 230b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int state; 231b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 232b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt state = atoi(cmd + 10); 233b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = wpa_driver_set_power_save(priv, state); 234991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (ret < 0) 235991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 236991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt else 237991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 238b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } else if (os_strncasecmp(cmd, "GETPOWER", 8) == 0) { 239b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt int state = -1; 240b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt 241b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = wpa_driver_get_power_save(priv, &state); 242991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (!ret && (state != -1)) { 243b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt ret = os_snprintf(buf, buf_len, "POWERMODE = %d\n", state); 244991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 245991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 246991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 247991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 248d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt } else { /* Use private command */ 249991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (os_strcasecmp(cmd, "BGSCAN-START") == 0) { 250991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt ret = wpa_driver_set_backgroundscan_params(priv); 251991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if (ret < 0) { 252991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt return ret; 253991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 254991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, "PNOFORCE 1", 11); 255991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else if (os_strcasecmp(cmd, "BGSCAN-STOP") == 0) { 256991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, "PNOFORCE 0", 11); 257991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 258991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt os_memcpy(buf, cmd, strlen(cmd) + 1); 259991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } 260d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt memset(&ifr, 0, sizeof(ifr)); 261d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt memset(&priv_cmd, 0, sizeof(priv_cmd)); 26230277c38a4fb41c7f71c790cd637f0d0aea94cc3Dmitry Shmidt os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 263d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 264d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.buf = buf; 265d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.used_len = buf_len; 266d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt priv_cmd.total_len = buf_len; 267d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ifr.ifr_data = &priv_cmd; 268d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 269991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) { 270d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__); 271991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt wpa_driver_send_hang_msg(drv); 272991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt } else { 273991c6863090c21e49229be18a6859d0ec5eaac17Dmitry Shmidt drv_errors = 0; 274d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ret = 0; 275d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt if ((os_strcasecmp(cmd, "LINKSPEED") == 0) || 2760428c19916e443cb002cba53263c3421ca6bd2d3Dmitry Shmidt (os_strcasecmp(cmd, "RSSI") == 0) || 2770428c19916e443cb002cba53263c3421ca6bd2d3Dmitry Shmidt (os_strcasecmp(cmd, "GETBAND") == 0)) 278d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt ret = strlen(buf); 279d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt 280d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s %s len = %d, %d", __func__, buf, ret, strlen(buf)); 281d261d2a4e8c8ba5d52a3f6d24a15404e5a3a49e6Dmitry Shmidt } 282b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt } 283b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt return ret; 284b11634b6f66e5ae56fe2212bd5d648157541c6e6Dmitry Shmidt} 285b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 286b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) 287b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 288b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 289b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 290b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt memset(buf, 0, sizeof(buf)); 291b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 292b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration); 293b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1); 294b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 295b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 296b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) 297b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 298b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_DRV_CMD_SIZE]; 299b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 300b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt memset(buf, 0, sizeof(buf)); 301b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 302b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow); 303b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf) + 1); 304b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 305b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 306b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidtint wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, 307b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *proberesp, 308b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *assocresp) 309b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt{ 310b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char buf[MAX_WPSP2PIE_CMD_SIZE]; 311b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt struct wpabuf *ap_wps_p2p_ie = NULL; 312b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char *_cmd = "SET_AP_WPS_P2P_IE"; 313b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt char *pbuf; 314b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int ret = 0; 315b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int i; 316b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt struct cmd_desc { 317b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt int cmd; 318b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt const struct wpabuf *src; 319b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } cmd_arr[] = { 320b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x1, beacon}, 321b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x2, proberesp}, 322b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {0x4, assocresp}, 323b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt {-1, NULL} 324b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt }; 325b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 326b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: Entry", __func__); 327b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt for (i = 0; cmd_arr[i].cmd != -1; i++) { 328b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt os_memset(buf, 0, sizeof(buf)); 329b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt pbuf = buf; 330b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt pbuf += sprintf(pbuf, "%s %d", _cmd, cmd_arr[i].cmd); 331b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt *pbuf++ = '\0'; 332b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt ap_wps_p2p_ie = cmd_arr[i].src ? 333b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpabuf_dup(cmd_arr[i].src) : NULL; 334b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt if (ap_wps_p2p_ie) { 335b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie)); 336b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, 337b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie)); 338b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt wpabuf_free(ap_wps_p2p_ie); 339b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt if (ret < 0) 340b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt break; 341b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } 342b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt } 343b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt 344b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt return ret; 345b05da5a8c808715098cae93ef1db1f2684f71c9fDmitry Shmidt} 346