summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Cerqueira <cyanogenmod@cerqueira.org>2013-11-01 20:36:26 +0000
committerGerrit Code Review <gerrit@cyanogenmod.org>2015-10-14 14:38:07 -0700
commit4cb0905dec737bcd366ad245bd647f4cf90eadd7 (patch)
treeb46e7ddd1129ccc86c80b9e494ec1c9972c3d9ab
parent3674b8ab31a628c5d0834890ba3549bf8badf4ea (diff)
downloadhardware_libhardware_legacy-4cb0905dec737bcd366ad245bd647f4cf90eadd7.zip
hardware_libhardware_legacy-4cb0905dec737bcd366ad245bd647f4cf90eadd7.tar.gz
hardware_libhardware_legacy-4cb0905dec737bcd366ad245bd647f4cf90eadd7.tar.bz2
wifi: support adding p2p0 when starting wpa_supplicant
For TI wlan chips in p2p mode we need this omapzoom cherry-pick to start p2p0 correctly. http://www.omapzoom.org/?p=platform/hardware/libhardware_legacy.git;a=commit;h=ccb4c24db795059f1df365d313d80c6b269bc55e By: Arik Nemtsov <arik@wizery.com> On: Tue, 31 Jul 2012 21:21:20 Original commit description: Add p2p0 using an NL80211 command when wpa_supplicant is started, and p2p_supported is enabled. Change-Id: Ibc0ad138513f024672642cc5764a81510aa38625 Signed-off-by: Hashcode <hashcode0f@gmail.com> From: Barak Bercovitz <barak@wizery.com> Date: Fri, 18 Oct 2013 12:41:32 +0300 Subject: [PATCH] wifi: remove p2p interface on supplicant stop wifi: remove p2p interface on supplicant stop remove p2p interface on wpa_supplicant stop so next time it is started it won't fail when trying to create p2p again Change-Id: I7a4c5e9a82a013afc75548d175d5850d67fcd927
-rw-r--r--Android.mk10
-rw-r--r--wifi/wifi.c246
2 files changed, 256 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
index 0a82a1f..cb3b439 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,6 +13,16 @@ LOCAL_SHARED_LIBRARIES := libcutils liblog
LOCAL_INCLUDES += $(LOCAL_PATH)
+ifdef USES_TI_MAC80211
+ifneq ($(wildcard external/libnl),)
+LOCAL_SHARED_LIBRARIES += libnl
+LOCAL_C_INCLUDES += external/libnl/include
+else
+LOCAL_STATIC_LIBRARIES := libnl_2
+LOCAL_C_INCLUDES += external/libnl-headers
+endif
+endif
+
LOCAL_CFLAGS += -DQEMU_HARDWARE
QEMU_HARDWARE := true
diff --git a/wifi/wifi.c b/wifi/wifi.c
index 7ee355a..cc76d21 100644
--- a/wifi/wifi.c
+++ b/wifi/wifi.c
@@ -24,6 +24,17 @@
#include <unistd.h>
#include <poll.h>
+#ifdef USES_TI_MAC80211
+#include <dirent.h>
+#include <net/if.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#include <linux/nl80211.h>
+#endif
+
#include "hardware_legacy/wifi.h"
#include "hardware_legacy/wifi_fst.h"
#ifdef LIBWPA_CLIENT_EXISTS
@@ -75,6 +86,13 @@ static char primary_iface[PROPERTY_VALUE_MAX];
// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
// sockets is in
+#ifdef USES_TI_MAC80211
+#define P2P_INTERFACE "p2p0"
+struct nl_sock *nl_soc;
+struct nl_cache *nl_cache;
+struct genl_family *nl80211;
+#endif
+
#ifndef WIFI_DRIVER_MODULE_ARG
#define WIFI_DRIVER_MODULE_ARG ""
#endif
@@ -443,6 +461,220 @@ int ensure_config_file_exists(const char *config_file, const char *config_file_t
return 0;
}
+#ifdef USES_TI_MAC80211
+static int init_nl()
+{
+ int err;
+
+ nl_soc = nl_socket_alloc();
+ if (!nl_soc) {
+ ALOGE("Failed to allocate netlink socket.");
+ return -ENOMEM;
+ }
+
+ if (genl_connect(nl_soc)) {
+ ALOGE("Failed to connect to generic netlink.");
+ err = -ENOLINK;
+ goto out_handle_destroy;
+ }
+
+ genl_ctrl_alloc_cache(nl_soc, &nl_cache);
+ if (!nl_cache) {
+ ALOGE("Failed to allocate generic netlink cache.");
+ err = -ENOMEM;
+ goto out_handle_destroy;
+ }
+
+ nl80211 = genl_ctrl_search_by_name(nl_cache, "nl80211");
+ if (!nl80211) {
+ ALOGE("nl80211 not found.");
+ err = -ENOENT;
+ goto out_cache_free;
+ }
+
+ return 0;
+
+out_cache_free:
+ nl_cache_free(nl_cache);
+out_handle_destroy:
+ nl_socket_free(nl_soc);
+ return err;
+}
+
+static void deinit_nl()
+{
+ genl_family_put(nl80211);
+ nl_cache_free(nl_cache);
+ nl_socket_free(nl_soc);
+}
+
+// ignore the "." and ".." entries
+static int dir_filter(const struct dirent *name)
+{
+ if (0 == strcmp("..", name->d_name) ||
+ 0 == strcmp(".", name->d_name))
+ return 0;
+
+ return 1;
+}
+
+// lookup the only active phy
+int phy_lookup()
+{
+ char buf[200];
+ int fd, pos;
+ struct dirent **namelist;
+ int n, i;
+
+ n = scandir("/sys/class/ieee80211", &namelist, dir_filter,
+ (int (*)(const struct dirent**, const struct dirent**))alphasort);
+ if (n != 1) {
+ ALOGE("unexpected - found %d phys in /sys/class/ieee80211", n);
+ for (i = 0; i < n; i++)
+ free(namelist[i]);
+ free(namelist);
+ return -1;
+ }
+
+ snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index",
+ namelist[0]->d_name);
+ free(namelist[0]);
+ free(namelist);
+
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ pos = read(fd, buf, sizeof(buf) - 1);
+ if (pos < 0) {
+ close(fd);
+ return -1;
+ }
+ buf[pos] = '\0';
+ close(fd);
+ return atoi(buf);
+}
+
+int nl_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+ int *ret = (int *)arg;
+ *ret = err->error;
+ return NL_STOP;
+}
+
+int nl_finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = (int *)arg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+int nl_ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = (int *)arg;
+ *ret = 0;
+ return NL_STOP;
+}
+
+static int execute_nl_interface_cmd(const char *iface,
+ enum nl80211_iftype type,
+ uint8_t cmd)
+{
+ struct nl_cb *cb;
+ struct nl_msg *msg;
+ int devidx = 0;
+ int err;
+ int add_interface = (cmd == NL80211_CMD_NEW_INTERFACE);
+
+ if (add_interface) {
+ devidx = phy_lookup();
+ } else {
+ devidx = if_nametoindex(iface);
+ if (devidx == 0) {
+ ALOGE("failed to translate ifname to idx");
+ return -errno;
+ }
+ }
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ ALOGE("failed to allocate netlink message");
+ return 2;
+ }
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ ALOGE("failed to allocate netlink callbacks");
+ err = 2;
+ goto out_free_msg;
+ }
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, 0, cmd, 0);
+
+ if (add_interface) {
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, devidx);
+ } else {
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
+ }
+
+ if (add_interface) {
+ NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, iface);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type);
+ }
+
+ err = nl_send_auto_complete(nl_soc, msg);
+ if (err < 0)
+ goto out;
+
+ err = 1;
+
+ nl_cb_err(cb, NL_CB_CUSTOM, nl_error_handler, &err);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_finish_handler, &err);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, &err);
+
+ while (err > 0)
+ nl_recvmsgs(nl_soc, cb);
+out:
+ nl_cb_put(cb);
+out_free_msg:
+ nlmsg_free(msg);
+ return err;
+nla_put_failure:
+ ALOGW("building message failed");
+ return 2;
+}
+
+int add_remove_p2p_interface(int add)
+{
+ int ret;
+
+ ret = init_nl();
+ if (ret != 0)
+ return ret;
+
+ if (add) {
+ ret = execute_nl_interface_cmd(P2P_INTERFACE, NL80211_IFTYPE_STATION,
+ NL80211_CMD_NEW_INTERFACE);
+ if (ret != 0) {
+ ALOGE("could not add P2P interface: %d", ret);
+ goto cleanup;
+ }
+ } else {
+ ret = execute_nl_interface_cmd(P2P_INTERFACE, NL80211_IFTYPE_STATION,
+ NL80211_CMD_DEL_INTERFACE);
+ if (ret != 0) {
+ ALOGE("could not remove P2P interface: %d", ret);
+ goto cleanup;
+ }
+ }
+
+ ALOGD("added/removed p2p interface. add: %d", add);
+
+cleanup:
+ deinit_nl();
+ return ret;
+}
+#endif /* USES_TI_MAC80211 */
+
int wifi_start_supplicant(int p2p_supported)
{
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
@@ -485,6 +717,13 @@ int wifi_start_supplicant(int p2p_supported)
ALOGE("Wi-Fi entropy file was not created");
}
+#ifdef USES_TI_MAC80211
+ if (p2p_supported && add_remove_p2p_interface(1) < 0) {
+ ALOGE("Wi-Fi - could not create p2p interface");
+ return -1;
+ }
+#endif
+
/* Clear out any stale socket files that might be left over. */
wpa_ctrl_cleanup();
@@ -549,6 +788,13 @@ int wifi_stop_supplicant(int p2p_supported)
return 0;
}
+#ifdef USES_TI_MAC80211
+ if (p2p_supported && add_remove_p2p_interface(0) < 0) {
+ ALOGE("Wi-Fi - could not remove p2p interface");
+ return -1;
+ }
+#endif
+
property_set("ctl.stop", supplicant_name);
sched_yield();