2 * Driver interaction with Linux nl80211/cfg80211 - Android specific
3 * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
5 * Copyright (c) 2009-2010, Atheros Communications
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
12 #include <sys/ioctl.h>
14 #include <netlink/genl/genl.h>
15 #include <netlink/genl/family.h>
16 #include <netlink/genl/ctrl.h>
19 #include "utils/common.h"
20 #include "driver_nl80211.h"
21 #include "android_drv.h"
24 typedef struct android_wifi_priv_cmd {
28 } android_wifi_priv_cmd;
30 static int drv_errors = 0;
32 static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
35 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
37 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
42 static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
44 struct wpa_driver_nl80211_data *drv = bss->drv;
46 android_wifi_priv_cmd priv_cmd;
47 char buf[MAX_DRV_CMD_SIZE];
50 os_memset(&ifr, 0, sizeof(ifr));
51 os_memset(&priv_cmd, 0, sizeof(priv_cmd));
52 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
54 os_memset(buf, 0, sizeof(buf));
55 os_strlcpy(buf, cmd, sizeof(buf));
58 priv_cmd.used_len = sizeof(buf);
59 priv_cmd.total_len = sizeof(buf);
60 ifr.ifr_data = &priv_cmd;
62 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
64 wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
66 wpa_driver_send_hang_msg(drv);
75 int android_pno_start(struct i802_bss *bss,
76 struct wpa_driver_scan_params *params)
78 struct wpa_driver_nl80211_data *drv = bss->drv;
80 android_wifi_priv_cmd priv_cmd;
81 int ret = 0, i = 0, bp;
82 char buf[WEXT_PNO_MAX_COMMAND_SIZE];
84 bp = WEXT_PNOSETUP_HEADER_SIZE;
85 os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
86 buf[bp++] = WEXT_PNO_TLV_PREFIX;
87 buf[bp++] = WEXT_PNO_TLV_VERSION;
88 buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
89 buf[bp++] = WEXT_PNO_TLV_RESERVED;
91 while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
92 /* Check that there is enough space needed for 1 more SSID, the
93 * other sections and null termination */
94 if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
95 WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
97 wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
98 params->ssids[i].ssid,
99 params->ssids[i].ssid_len);
100 buf[bp++] = WEXT_PNO_SSID_SECTION;
101 buf[bp++] = params->ssids[i].ssid_len;
102 os_memcpy(&buf[bp], params->ssids[i].ssid,
103 params->ssids[i].ssid_len);
104 bp += params->ssids[i].ssid_len;
108 buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
109 os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
110 WEXT_PNO_SCAN_INTERVAL);
111 bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
113 buf[bp++] = WEXT_PNO_REPEAT_SECTION;
114 os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
116 bp += WEXT_PNO_REPEAT_LENGTH;
118 buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
119 os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
120 WEXT_PNO_MAX_REPEAT);
121 bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
123 memset(&ifr, 0, sizeof(ifr));
124 memset(&priv_cmd, 0, sizeof(priv_cmd));
125 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
128 priv_cmd.used_len = bp;
129 priv_cmd.total_len = bp;
130 ifr.ifr_data = &priv_cmd;
132 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
135 wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
137 wpa_driver_send_hang_msg(drv);
143 return android_priv_cmd(bss, "PNOFORCE 1");
147 int android_pno_stop(struct i802_bss *bss)
149 return android_priv_cmd(bss, "PNOFORCE 0");
154 #ifdef ANDROID_LIB_STUB
156 int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
162 int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
168 int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
174 int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
175 const struct wpabuf *proberesp,
176 const struct wpabuf *assocresp)
181 #endif /* ANDROID_LIB_STUB */
182 #endif /* ANDROID_P2P */
185 int android_nl_socket_set_nonblocking(struct nl_handle *handle)
187 return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);