]>
Commit | Line | Data |
---|---|---|
70a96c81 JM |
1 | /* |
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 | |
6 | * | |
7 | * This software may be distributed under the terms of the BSD license. | |
8 | * See README for more details. | |
9 | */ | |
10 | ||
11 | #include "includes.h" | |
12 | #include <sys/ioctl.h> | |
13 | #include <net/if.h> | |
14 | #include <netlink/genl/genl.h> | |
15 | #include <netlink/genl/family.h> | |
16 | #include <netlink/genl/ctrl.h> | |
f0399656 | 17 | #include <fcntl.h> |
70a96c81 JM |
18 | |
19 | #include "utils/common.h" | |
20 | #include "driver_nl80211.h" | |
21 | #include "android_drv.h" | |
22 | ||
23 | ||
24 | typedef struct android_wifi_priv_cmd { | |
25 | char *buf; | |
26 | int used_len; | |
27 | int total_len; | |
28 | } android_wifi_priv_cmd; | |
29 | ||
30 | static int drv_errors = 0; | |
31 | ||
32 | static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) | |
33 | { | |
34 | drv_errors++; | |
35 | if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { | |
36 | drv_errors = 0; | |
37 | wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); | |
38 | } | |
39 | } | |
40 | ||
41 | ||
42 | static int android_priv_cmd(struct i802_bss *bss, const char *cmd) | |
43 | { | |
44 | struct wpa_driver_nl80211_data *drv = bss->drv; | |
45 | struct ifreq ifr; | |
46 | android_wifi_priv_cmd priv_cmd; | |
47 | char buf[MAX_DRV_CMD_SIZE]; | |
48 | int ret; | |
49 | ||
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); | |
53 | ||
54 | os_memset(buf, 0, sizeof(buf)); | |
55 | os_strlcpy(buf, cmd, sizeof(buf)); | |
56 | ||
57 | priv_cmd.buf = buf; | |
58 | priv_cmd.used_len = sizeof(buf); | |
59 | priv_cmd.total_len = sizeof(buf); | |
60 | ifr.ifr_data = &priv_cmd; | |
61 | ||
62 | ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); | |
63 | if (ret < 0) { | |
64 | wpa_printf(MSG_ERROR, "%s: failed to issue private commands", | |
65 | __func__); | |
66 | wpa_driver_send_hang_msg(drv); | |
67 | return ret; | |
68 | } | |
69 | ||
70 | drv_errors = 0; | |
71 | return 0; | |
72 | } | |
73 | ||
74 | ||
75 | int android_pno_start(struct i802_bss *bss, | |
76 | struct wpa_driver_scan_params *params) | |
77 | { | |
78 | struct wpa_driver_nl80211_data *drv = bss->drv; | |
79 | struct ifreq ifr; | |
80 | android_wifi_priv_cmd priv_cmd; | |
81 | int ret = 0, i = 0, bp; | |
82 | char buf[WEXT_PNO_MAX_COMMAND_SIZE]; | |
83 | ||
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; | |
90 | ||
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)) | |
96 | break; | |
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; | |
105 | i++; | |
106 | } | |
107 | ||
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; | |
112 | ||
113 | buf[bp++] = WEXT_PNO_REPEAT_SECTION; | |
114 | os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x", | |
115 | WEXT_PNO_REPEAT); | |
116 | bp += WEXT_PNO_REPEAT_LENGTH; | |
117 | ||
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; | |
122 | ||
123 | memset(&ifr, 0, sizeof(ifr)); | |
124 | memset(&priv_cmd, 0, sizeof(priv_cmd)); | |
125 | os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); | |
126 | ||
127 | priv_cmd.buf = buf; | |
128 | priv_cmd.used_len = bp; | |
129 | priv_cmd.total_len = bp; | |
130 | ifr.ifr_data = &priv_cmd; | |
131 | ||
132 | ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr); | |
133 | ||
134 | if (ret < 0) { | |
135 | wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d", | |
136 | ret); | |
137 | wpa_driver_send_hang_msg(drv); | |
138 | return ret; | |
139 | } | |
140 | ||
141 | drv_errors = 0; | |
142 | ||
143 | return android_priv_cmd(bss, "PNOFORCE 1"); | |
144 | } | |
145 | ||
146 | ||
147 | int android_pno_stop(struct i802_bss *bss) | |
148 | { | |
149 | return android_priv_cmd(bss, "PNOFORCE 0"); | |
150 | } | |
151 | ||
152 | ||
153 | #ifdef ANDROID_P2P | |
a1407217 | 154 | #ifdef ANDROID_LIB_STUB |
70a96c81 JM |
155 | |
156 | int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) | |
157 | { | |
158 | return 0; | |
159 | } | |
160 | ||
161 | ||
162 | int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) | |
163 | { | |
164 | return 0; | |
165 | } | |
166 | ||
167 | ||
168 | int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) | |
169 | { | |
170 | return -1; | |
171 | } | |
172 | ||
173 | ||
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) | |
177 | { | |
178 | return 0; | |
179 | } | |
180 | ||
a1407217 | 181 | #endif /* ANDROID_LIB_STUB */ |
70a96c81 JM |
182 | #endif /* ANDROID_P2P */ |
183 | ||
184 | ||
185 | int android_nl_socket_set_nonblocking(struct nl_handle *handle) | |
186 | { | |
187 | return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK); | |
188 | } | |
189 | ||
190 |