From c813f1497eda7ac94cf50ba7376157513e5c0ba6 Mon Sep 17 00:00:00 2001 From: Hashcode Date: Fri, 14 Dec 2012 23:30:11 -0800 Subject: 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 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 --- wifi/wifi.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) (limited to 'wifi') diff --git a/wifi/wifi.c b/wifi/wifi.c index 5ed195a..68e51ca 100644 --- a/wifi/wifi.c +++ b/wifi/wifi.c @@ -23,6 +23,17 @@ #include #include +#ifdef USES_TI_MAC80211 +#include +#include +#include +#include +#include +#include +#include +#include "nl80211.h" +#endif + #include "hardware_legacy/wifi.h" #include "libwpa_client/wpa_ctrl.h" @@ -65,6 +76,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 @@ -547,6 +565,220 @@ void wifi_wpa_ctrl_cleanup(void) closedir(dir); } +#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'}; @@ -587,6 +819,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. */ wifi_wpa_ctrl_cleanup(); -- cgit v1.1