tAdd Linux support for the wifi plugin - spoon - dwm status utility (2f30 fork)
 (HTM) git clone git://src.adamsgaard.dk/spoon
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 39a4ec480bc9db2e4fca1506856309dc884d1fb9
 (DIR) parent 36856fa7ba39356dcf456226797ff588a5733999
 (HTM) Author: lostd <lostd@2f30.org>
       Date:   Wed,  2 Nov 2016 14:37:07 +0100
       
       Add Linux support for the wifi plugin
       
       Diffstat:
         M util.h                              |      10 ++++++++++
         M wifi.c                              |      93 +++++++++++++++++++++++++++++--
       
       2 files changed, 99 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git a/util.h b/util.h
       t@@ -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
 (DIR) diff --git a/wifi.c b/wifi.c
       t@@ -1,5 +1,8 @@
        #include <err.h>
       +#include <ifaddrs.h>
        #include <stdio.h>
       +#include <string.h>
       +#include <unistd.h>
        
        #include "util.h"
        
       t@@ -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)
        {
       t@@ -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