+
+ if (wcfg.has_essid && wcfg.essid_on) {
+ info->flags |= WIRELESS_INFO_FLAG_HAS_ESSID;
+ strncpy(&info->essid[0], wcfg.essid, IW_ESSID_MAX_SIZE);
+ info->essid[IW_ESSID_MAX_SIZE] = '\0';
+ }
+
+ if (wcfg.has_freq) {
+ info->frequency = wcfg.freq;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_FREQUENCY;
+ }
+
+ /* If the function iw_get_stats does not return proper stats, the
+ * wifi is considered as down.
+ * Since ad-hoc network does not have theses stats, we need to return
+ * here for this mode. */
+ if (wcfg.mode == 1) {
+ close(skfd);
+ return 1;
+ }
+
+ /* Wireless quality is a relative value in a driver-specific range.
+ * Signal and noise level can be either relative or absolute values
+ * in dBm. Furthermore, noise and quality can be expressed directly
+ * in dBm or in RCPI (802.11k), which we convert to dBm. When those
+ * values are expressed directly in dBm, they range from -192 to 63,
+ * and since the values are packed into 8 bits, we need to perform
+ * 8-bit arithmetic on them. Assume absolute values if everything
+ * else fails (driver bug). */
+
+ iwrange range;
+ if (iw_get_range_info(skfd, interface, &range) < 0) {
+ close(skfd);
+ return 0;
+ }
+
+ iwstats stats;
+ if (iw_get_stats(skfd, interface, &stats, &range, 1) < 0) {
+ close(skfd);
+ return 0;
+ }
+
+ if (stats.qual.level != 0 || (stats.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI))) {
+ if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
+ info->quality = stats.qual.qual;
+ info->quality_max = range.max_qual.qual;
+ info->quality_average = range.avg_qual.qual;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
+ }
+
+ if (stats.qual.updated & IW_QUAL_RCPI) {
+ if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
+ info->signal_level = stats.qual.level / 2.0 - 110 + 0.5;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
+ }
+ if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
+ info->noise_level = stats.qual.noise / 2.0 - 110 + 0.5;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
+ }
+ } else {
+ if ((stats.qual.updated & IW_QUAL_DBM) || stats.qual.level > range.max_qual.level) {
+ if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
+ info->signal_level = stats.qual.level;
+ if (info->signal_level > 63)
+ info->signal_level -= 256;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
+ }
+ if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
+ info->noise_level = stats.qual.noise;
+ if (info->noise_level > 63)
+ info->noise_level -= 256;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
+ }
+ } else {
+ if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
+ info->signal_level = stats.qual.level;
+ info->signal_level_max = range.max_qual.level;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
+ }
+ if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
+ info->noise_level = stats.qual.noise;
+ info->noise_level_max = range.max_qual.noise;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
+ }
+ }
+ }
+ } else {
+ if (!(stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
+ info->quality = stats.qual.qual;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_QUALITY;
+ }
+ if (!(stats.qual.updated & IW_QUAL_LEVEL_INVALID)) {
+ info->quality = stats.qual.level;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_SIGNAL;
+ }
+ if (!(stats.qual.updated & IW_QUAL_NOISE_INVALID)) {
+ info->quality = stats.qual.noise;
+ info->flags |= WIRELESS_INFO_FLAG_HAS_NOISE;
+ }
+ }
+
+ struct iwreq wrq;
+ if (iw_get_ext(skfd, interface, SIOCGIWRATE, &wrq) >= 0)
+ info->bitrate = wrq.u.bitrate.value;
+
+ close(skfd);
+ return 1;