150276Speter/* 262449Speter * Driver interaction with Linux nl80211/cfg80211 - Android specific 350276Speter * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> 450276Speter * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net> 550276Speter * Copyright (c) 2009-2010, Atheros Communications 650276Speter * 750276Speter * This software may be distributed under the terms of the BSD license. 850276Speter * See README for more details. 950276Speter */ 1050276Speter 1150276Speter#include "includes.h" 1250276Speter#include <sys/ioctl.h> 1350276Speter#include <net/if.h> 1450276Speter#include <netlink/genl/genl.h> 1550276Speter#include <netlink/genl/family.h> 1650276Speter#include <netlink/genl/ctrl.h> 1750276Speter#include <fcntl.h> 1850276Speter 1950276Speter#include "utils/common.h" 2050276Speter#include "driver_nl80211.h" 2150276Speter#include "android_drv.h" 2250276Speter 2350276Speter 2450276Spetertypedef struct android_wifi_priv_cmd { 2550276Speter char *buf; 2650276Speter int used_len; 2750276Speter int total_len; 2850276Speter} android_wifi_priv_cmd; 2950276Speter 3050276Speterstatic int drv_errors = 0; 3150276Speter 3250276Speterstatic void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) 3350276Speter{ 3450276Speter drv_errors++; 3550276Speter if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { 3650276Speter drv_errors = 0; 3750276Speter wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); 3850276Speter } 3950276Speter} 4050276Speter 4150276Speter 4250276Speterstatic int android_priv_cmd(struct i802_bss *bss, const char *cmd) 4350276Speter{ 4450276Speter struct wpa_driver_nl80211_data *drv = bss->drv; 4562449Speter struct ifreq ifr; 4650276Speter android_wifi_priv_cmd priv_cmd; 4750276Speter char buf[MAX_DRV_CMD_SIZE]; 4850276Speter int ret; 4962449Speter 5062449Speter os_memset(&ifr, 0, sizeof(ifr)); 5162449Speter os_memset(&priv_cmd, 0, sizeof(priv_cmd)); 5262449Speter os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 5350276Speter 5462449Speter os_memset(buf, 0, sizeof(buf)); 5562449Speter os_strlcpy(buf, cmd, sizeof(buf)); 5650276Speter 5762449Speter priv_cmd.buf = buf; 5850276Speter priv_cmd.used_len = sizeof(buf); 5962449Speter priv_cmd.total_len = sizeof(buf); 6062449Speter ifr.ifr_data = &priv_cmd; 6150276Speter 6262449Speter ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); 6362449Speter if (ret < 0) { 6462449Speter wpa_printf(MSG_ERROR, "%s: failed to issue private commands", 6550276Speter __func__); 6662449Speter wpa_driver_send_hang_msg(drv); 6750276Speter return ret; 6862449Speter } 6950276Speter 7062449Speter drv_errors = 0; 7150276Speter return 0; 7250276Speter} 7362449Speter 7462449Speter 7550276Speterint android_pno_start(struct i802_bss *bss, 7662449Speter struct wpa_driver_scan_params *params) 7762449Speter{ 7862449Speter struct wpa_driver_nl80211_data *drv = bss->drv; 7950276Speter struct ifreq ifr; 8050276Speter android_wifi_priv_cmd priv_cmd; 8162449Speter int ret = 0, i = 0, bp; 8262449Speter char buf[WEXT_PNO_MAX_COMMAND_SIZE]; 8350276Speter 8462449Speter bp = WEXT_PNOSETUP_HEADER_SIZE; 8562449Speter os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp); 8650276Speter buf[bp++] = WEXT_PNO_TLV_PREFIX; 8750276Speter buf[bp++] = WEXT_PNO_TLV_VERSION; 8850276Speter buf[bp++] = WEXT_PNO_TLV_SUBVERSION; 8950276Speter buf[bp++] = WEXT_PNO_TLV_RESERVED; 9050276Speter 9150276Speter while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) { 9250276Speter /* Check that there is enough space needed for 1 more SSID, the 9350276Speter * other sections and null termination */ 9462449Speter if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN + 9562449Speter WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf)) 9662449Speter break; 9750276Speter wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan", 9850276Speter params->ssids[i].ssid, 9950276Speter params->ssids[i].ssid_len); 10050276Speter buf[bp++] = WEXT_PNO_SSID_SECTION; 10150276Speter buf[bp++] = params->ssids[i].ssid_len; 10250276Speter os_memcpy(&buf[bp], params->ssids[i].ssid, 10350276Speter params->ssids[i].ssid_len); 10450276Speter bp += params->ssids[i].ssid_len; 10550276Speter i++; 10650276Speter } 10750276Speter 10850276Speter buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION; 10950276Speter os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x", 11050276Speter WEXT_PNO_SCAN_INTERVAL); 11150276Speter bp += WEXT_PNO_SCAN_INTERVAL_LENGTH; 11250276Speter 11362449Speter buf[bp++] = WEXT_PNO_REPEAT_SECTION; 11462449Speter os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", 11550276Speter WEXT_PNO_REPEAT); 11662449Speter bp += WEXT_PNO_REPEAT_LENGTH; 11762449Speter 11862449Speter buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION; 11962449Speter os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x", 12062449Speter WEXT_PNO_MAX_REPEAT); 12162449Speter bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1; 12250276Speter 12350276Speter memset(&ifr, 0, sizeof(ifr)); 12450276Speter memset(&priv_cmd, 0, sizeof(priv_cmd)); 12550276Speter os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); 12650276Speter 12750276Speter priv_cmd.buf = buf; 12862449Speter priv_cmd.used_len = bp; 12962449Speter priv_cmd.total_len = bp; 13050276Speter ifr.ifr_data = &priv_cmd; 13162449Speter 13262449Speter ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); 13362449Speter 13462449Speter if (ret < 0) { 13550276Speter wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", 13662449Speter ret); 13762449Speter wpa_driver_send_hang_msg(drv); 13862449Speter return ret; 13962449Speter } 14062449Speter 14162449Speter drv_errors = 0; 14262449Speter 14362449Speter return android_priv_cmd(bss, "PNOFORCE 1"); 14462449Speter} 14562449Speter 14662449Speter 14762449Speterint android_pno_stop(struct i802_bss *bss) 14862449Speter{ 14962449Speter return android_priv_cmd(bss, "PNOFORCE 0"); 15062449Speter} 15162449Speter 15262449Speter 15362449Speter#ifdef ANDROID_P2P 15462449Speter#ifdef ANDROID_LIB_STUB 15562449Speter 15662449Speterint wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) 15762449Speter{ 15862449Speter return 0; 15962449Speter} 16062449Speter 16162449Speter 16262449Speterint wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) 16362449Speter{ 16462449Speter return 0; 16550276Speter} 16662449Speter 16762449Speter 16862449Speterint wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) 16962449Speter{ 17050276Speter return -1; 17162449Speter} 17250276Speter 17362449Speter 17462449Speterint wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, 17562449Speter const struct wpabuf *proberesp, 17650276Speter const struct wpabuf *assocresp) 17750276Speter{ 17862449Speter return 0; 17962449Speter} 18050276Speter 18150276Speter#endif /* ANDROID_LIB_STUB */ 18250276Speter#endif /* ANDROID_P2P */ 18350276Speter 18450276Speter 18550276Speterint android_nl_socket_set_nonblocking(struct nl_sock *handle) 18650276Speter{ 18750276Speter return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK); 18850276Speter} 18950276Speter