wext: Fix scan result signal levels when driver reports in dBm
[libeap.git] / src / drivers / driver_wext.c
index 2223783..f0de6aa 100644 (file)
@@ -635,6 +635,19 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
                   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
                   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
                   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
+
+       if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+               wpa_printf(MSG_DEBUG, "WEXT: Interface down");
+               drv->if_disabled = 1;
+               wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+       }
+
+       if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
+               wpa_printf(MSG_DEBUG, "WEXT: Interface up");
+               drv->if_disabled = 0;
+               wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+       }
+
        /*
         * Some drivers send the association event before the operup event--in
         * this case, lifting operstate in wpa_driver_wext_set_operstate()
@@ -690,9 +703,11 @@ static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
 
 static void wpa_driver_wext_rfkill_blocked(void *ctx)
 {
-       struct wpa_driver_wext_data *drv = ctx;
        wpa_printf(MSG_DEBUG, "WEXT: RFKILL blocked");
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+       /*
+        * This may be for any interface; use ifdown event to disable
+        * interface.
+        */
 }
 
 
@@ -705,7 +720,7 @@ static void wpa_driver_wext_rfkill_unblocked(void *ctx)
                           "after rfkill unblock");
                return;
        }
-       wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+       /* rtnetlink ifup handler will report interface as enabled */
 }
 
 
@@ -802,6 +817,7 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
                        wpa_printf(MSG_DEBUG, "WEXT: Could not yet enable "
                                   "interface '%s' due to rfkill",
                                   drv->ifname);
+                       drv->if_disabled = 1;
                        send_rfkill_event = 1;
                } else {
                        wpa_printf(MSG_ERROR, "WEXT: Could not set "
@@ -1101,7 +1117,8 @@ static void wext_get_scan_freq(struct iw_event *iwe,
 }
 
 
-static void wext_get_scan_qual(struct iw_event *iwe,
+static void wext_get_scan_qual(struct wpa_driver_wext_data *drv,
+                              struct iw_event *iwe,
                               struct wext_scan_data *res)
 {
        res->res.qual = iwe->u.qual.qual;
@@ -1115,6 +1132,14 @@ static void wext_get_scan_qual(struct iw_event *iwe,
                res->res.flags |= WPA_SCAN_NOISE_INVALID;
        if (iwe->u.qual.updated & IW_QUAL_DBM)
                res->res.flags |= WPA_SCAN_LEVEL_DBM;
+       if ((iwe->u.qual.updated & IW_QUAL_DBM) ||
+           ((iwe->u.qual.level != 0) &&
+            (iwe->u.qual.level > drv->max_level))) {
+               if (iwe->u.qual.level >= 64)
+                       res->res.level -= 0x100;
+               if (iwe->u.qual.noise >= 64)
+                       res->res.noise -= 0x100;
+       }
 }
 
 
@@ -1390,7 +1415,7 @@ struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
                        wext_get_scan_freq(iwe, &data);
                        break;
                case IWEVQUAL:
-                       wext_get_scan_qual(iwe, &data);
+                       wext_get_scan_qual(drv, iwe, &data);
                        break;
                case SIOCGIWENCODE:
                        wext_get_scan_encode(iwe, &data);
@@ -1488,6 +1513,8 @@ static int wpa_driver_wext_get_range(void *priv)
                           "assuming WPA is not supported");
        }
 
+       drv->max_level = range->max_qual.level;
+
        os_free(range);
        return 0;
 }