diff --git a/AUTHORS b/AUTHORS index 3f4fc2f6..bbc4ece8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -163,6 +163,9 @@ Roman Bogorodskiy FreeBSD support BMPx support +Stepan Zastupov + WiFi signal level detection support on FreeBSD + Szymon Boniecki Reads current LC_TIME diff --git a/ChangeLog b/ChangeLog index db136ac8..445d52a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ # $Id$ +2006-10-18 + * Implement WiFi signal level detection on FreeBSD (patch + by Stepan Zastupov) + 2006-10-04 * Fix buffer overflow in parsing LC_ALL, LC_CTYPE and LANG environment variables and fix crash for users with locale diff --git a/src/freebsd.c b/src/freebsd.c index 305ab755..32e1dadd 100644 --- a/src/freebsd.c +++ b/src/freebsd.c @@ -14,9 +14,13 @@ #include #include #include +#include #include #include +#include +#include +#include #include #include @@ -27,6 +31,8 @@ #include #include +#include + #include "conky.h" #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof (var)) @@ -511,7 +517,7 @@ get_freq(char *p_client_buffer, size_t client_buffer_size, if (!p_client_buffer || client_buffer_size <= 0 || !p_format || divisor <= 0) - return; + return 0; if (GETSYSCTL(freq_sysctl, freq) == 0) snprintf(p_client_buffer, client_buffer_size, @@ -532,7 +538,66 @@ update_top() void update_wifi_stats() { - /* XXX */ + struct ifreq ifr; /* interface stats */ + struct wi_req wireq; + struct net_stat * ns; + struct ifaddrs *ifap, *ifa; + struct ifmediareq ifmr; + int s; + + /* + * Get iface table + */ + if (getifaddrs(&ifap) < 0) + return; + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + ns = get_net_stat((const char *) ifa->ifa_name); + + if (!strcmp(ifa->ifa_name, "lo0") || + !strncmp(ifa->ifa_name, "fwe", 3) || + !strncmp(ifa->ifa_name, "tun", 3)) + continue; + + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + /* Get media type */ + bzero(&ifmr, sizeof(ifmr)); + strncpy(ifmr.ifm_name, ifa->ifa_name, strlen(ifmr.ifm_name) - 1); + ifmr.ifm_name[sizeof(ifmr.ifm_name) - 1] = '\0'; + if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { + perror("ioctl (getting media type)"); + exit(1); + } + /* + * We can monitor only wireless interfaces + * which not in hostap mode + */ + if ((ifmr.ifm_active & IFM_IEEE80211) && + !(ifmr.ifm_active & IFM_IEEE80211_HOSTAP)) { + /* Get wi status */ + bzero(&ifr, sizeof(ifr)); + strncpy(ifr.ifr_name, ifa->ifa_name, strlen(ifr.ifr_name) - 1); + ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; + wireq.wi_type = WI_RID_COMMS_QUALITY; + wireq.wi_len = WI_MAX_DATALEN; + ifr.ifr_data = (void *) &wireq; + + if (ioctl(s, SIOCGWAVELAN, (caddr_t) &ifr) < 0) { + perror("ioctl (getting wi status)"); + exit(1); + } + + /* + * wi_val[0] = quality + * wi_val[1] = signal + * wi_val[2] = noise + */ + ns->linkstatus = (int) wireq.wi_val[1]; + } + + close(s); + } } void update_diskio()