diff options
author | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2013-11-01 20:36:26 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2015-10-14 14:38:07 -0700 |
commit | 4cb0905dec737bcd366ad245bd647f4cf90eadd7 (patch) | |
tree | b46e7ddd1129ccc86c80b9e494ec1c9972c3d9ab /wifi | |
parent | 3674b8ab31a628c5d0834890ba3549bf8badf4ea (diff) | |
download | hardware_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
Diffstat (limited to 'wifi')
-rw-r--r-- | wifi/wifi.c | 246 |
1 files changed, 246 insertions, 0 deletions
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(); |