spoon

set dwm status
git clone git://git.2f30.org/spoon.git
Log | Files | Refs | LICENSE

commit 39a4ec480bc9db2e4fca1506856309dc884d1fb9
parent 36856fa7ba39356dcf456226797ff588a5733999
Author: lostd <lostd@2f30.org>
Date:   Wed Nov  2 14:37:07 +0100

Add Linux support for the wifi plugin

Diffstat:
util.h | 10++++++++++
wifi.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 99 insertions(+), 4 deletions(-)
diff --git a/util.h b/util.h @@ -2,3 +2,13 @@ size_t strlcat(char *, const char *, size_t); #undef strlcpy size_t strlcpy(char *, const char *, size_t); + +#ifdef DEBUG +#define DPRINTF_S(x) printf(#x "=%s\n", x) +#define DPRINTF_U(x) printf(#x "=%u\n", x) +#define DPRINTF_D(x) printf(#x "=%d\n", x) +#else +#define DPRINTF_S(x) +#define DPRINTF_U(x) +#define DPRINTF_D(x) +#endif diff --git a/wifi.c b/wifi.c @@ -1,5 +1,8 @@ #include <err.h> +#include <ifaddrs.h> #include <stdio.h> +#include <string.h> +#include <unistd.h> #include "util.h" @@ -32,10 +35,6 @@ wifiprint(char *buf, size_t len, int quality) #include <net80211/ieee80211.h> #include <net80211/ieee80211_ioctl.h> -#include <ifaddrs.h> -#include <string.h> -#include <unistd.h> - int wifiread(void *arg, char *buf, size_t len) { @@ -105,4 +104,90 @@ wifiread(void *arg, char *buf, size_t len) return 0; return -1; } +#elif __linux__ +#include <sys/types.h> +#include <sys/socket.h> + +#include <linux/wireless.h> + +int +wifiread(void *arg, char *buf, size_t len) +{ + struct ifaddrs *ifa, *ifas; + struct iw_quality *max_qual, *qual; + struct iw_statistics stats; + struct iw_range range; + struct iwreq wrq; + int quality = -1; + int level; + int ret, fd; + + if (getifaddrs(&ifas) < 0) { + warn("getifaddrs"); + return -1; + } + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd == -1) { + warn("socket"); + return -1; + } + for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) { + DPRINTF_S(ifa->ifa_name); + memset(&wrq, 0, sizeof(wrq)); + strlcpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ); + ret = ioctl(fd, SIOCGIWNAME, &wrq); + if (ret != 0) + continue; + memset(&wrq, 0, sizeof(wrq)); + strlcpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ); + wrq.u.data.pointer = &range; + wrq.u.data.length = sizeof(range); + memset(&range, 0, sizeof(range)); + ret = ioctl(fd, SIOCGIWRANGE, &wrq); + if (ret < 0) + warnx("cannot get wifi range"); + memset(&wrq, 0, sizeof(wrq)); + strlcpy(wrq.ifr_name, ifa->ifa_name, IFNAMSIZ); + wrq.u.data.pointer = &stats; + wrq.u.data.length = sizeof(stats); + wrq.u.data.flags = 1; + memset(&stats, 0, sizeof(stats)); + ret = ioctl(fd, SIOCGIWSTATS, &wrq); + if (ret < 0) + warnx("cannot get wifi stats"); + max_qual = &range.max_qual; + qual = &stats.qual; + DPRINTF_U(max_qual->qual); + DPRINTF_U(max_qual->level); + DPRINTF_U(qual->qual); + DPRINTF_U(qual->level); + if (max_qual->qual != 0) { + /* driver provides a quality metric */ + quality = (unsigned) + (((float)qual->qual / max_qual->qual) * 100); + } else if (max_qual->level != 0) { + /* driver provides signal strength (RSSI) */ + quality = (unsigned) + (((float)qual->level / max_qual->level) * 100); + } else if (max_qual->level == 0) { + /* driver provides absolute dBm values */ + level = qual->level - 0x100; + if (level <= -100) + quality = 0; + else if (level >= -50) + quality = 100; + else + quality = 2 * (level + 100); + } + break; + } + close(fd); + freeifaddrs(ifas); + + DPRINTF_D(quality); + if (quality == -1) + return -1; + wifiprint(buf, len, quality); + return 0; +} #endif