]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/blobdiff - src/drivers/driver_nl80211.c
nl80211: fix warnings
[build-utilities/hostap.git] / src / drivers / driver_nl80211.c
index d5ec17720ad51721e42372329fcd99d18c6c4ca0..4a04402c20e5533c1ea02c197bb78bb3691f6708 100644 (file)
@@ -1900,6 +1900,10 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
                wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
                           "event: RSSI low");
                ed.signal_change.above_threshold = 0;
+       } else if (event == NL80211_CQM_RSSI_BEACON_LOSS) {
+               wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
+                          "event: beacon loss!");
+               wpa_supplicant_event(drv->ctx, EVENT_START_ROAMING, &ed);
        } else
                return;
 
@@ -1922,6 +1926,25 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static void nl80211_roaming_support_event(struct wpa_driver_nl80211_data *drv,
+                                         struct nlattr *tb[])
+{
+       int enabled;
+       enum wpa_event_type event;
+
+       enabled = (tb[NL80211_ATTR_ROAMING_DISABLED] == NULL);
+
+       if (enabled)
+               event = EVENT_ROAMING_ENABLED;
+       else
+               event = EVENT_ROAMING_DISABLED;
+
+       wpa_printf(MSG_DEBUG, "nl80211: roaming %s",
+                  enabled ? "enabled" : "disabled");
+
+       wpa_supplicant_event(drv->ctx, event, NULL);
+}
+
 static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
                                      struct nlattr **tb)
 {
@@ -2174,6 +2197,9 @@ static void do_process_drv_event(struct wpa_driver_nl80211_data *drv,
        case NL80211_CMD_NOTIFY_CQM:
                nl80211_cqm_event(drv, tb);
                break;
+       case NL80211_CMD_ROAMING_SUPPORT:
+               nl80211_roaming_support_event(drv, tb);
+               break;
        case NL80211_CMD_REG_CHANGE:
                wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
                wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
@@ -2519,6 +2545,12 @@ broken_combination:
        if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
                capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
 
+       if (tb[NL80211_ATTR_FEATURE_FLAGS]) {
+               int features = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]);
+               if (features & NL80211_FEATURE_SCHED_SCAN_INTERVALS)
+                       capa->sched_scan_intervals_supported = 1;
+       }
+
        if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])
                capa->max_remain_on_chan =
                        nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
@@ -3597,12 +3629,16 @@ nla_put_failure:
  * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
  * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
  * @params: Scan parameters
- * @interval: Interval between scan cycles in milliseconds
+ * @long_interval: interval between scan cycles after end of short cycles
+ * @short_interval: interval between initial short scan cycles
+ * @num_short_intervals: number of interval short scan intervals
  * Returns: 0 on success, -1 on failure or if not supported
  */
 static int wpa_driver_nl80211_sched_scan(void *priv,
                                         struct wpa_driver_scan_params *params,
-                                        u32 interval)
+                                        u32 long_interval,
+                                        u32 short_interval,
+                                        u8 num_short_intervals)
 {
        struct i802_bss *bss = priv;
        struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -3634,7 +3670,17 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
 
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
-       NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
+       NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, long_interval);
+
+       if (drv->capa.sched_scan_intervals_supported) {
+               NLA_PUT_U32(msg,
+                           NL80211_ATTR_SCHED_SCAN_SHORT_INTERVAL,
+                           short_interval);
+
+               NLA_PUT_U8(msg,
+                          NL80211_ATTR_SCHED_SCAN_NUM_SHORT_INTERVALS,
+                          num_short_intervals);
+       }
 
        if (drv->num_filter_ssids &&
            (int) drv->num_filter_ssids <= drv->capa.max_match_sets) {
@@ -3699,8 +3745,9 @@ static int wpa_driver_nl80211_sched_scan(void *priv,
                goto nla_put_failure;
        }
 
-       wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
-                  "scan interval %d msec", ret, interval);
+       wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) "
+                  "intervals: short=%d ms long=%d ms num_short_intervals=%d"
+                  , ret, short_interval, long_interval, num_short_intervals);
 
 nla_put_failure:
        nlmsg_free(ssids);
@@ -8373,6 +8420,14 @@ static int wpa_driver_nl80211_deinit_ap(void *priv)
        return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
 }
 
+static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
+               return -1;
+       return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
+}
 
 static void wpa_driver_nl80211_resume(void *priv)
 {
@@ -8722,6 +8777,7 @@ nl80211_self_filter_get_pattern_handler(u8 *buf, int buflen, void *arg)
 }
 
 static struct rx_filter rx_filters[] = {
+       /* ID 0 */
        {.name = "self",
         .pattern = {},
         .pattern_len = 6,
@@ -8730,6 +8786,7 @@ static struct rx_filter rx_filters[] = {
         .get_pattern_handler = nl80211_self_filter_get_pattern_handler,
        },
 
+       /* ID 1 */
        {.name = "bcast",
         .pattern = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
         .pattern_len = 6,
@@ -8737,6 +8794,7 @@ static struct rx_filter rx_filters[] = {
         .mask_len = 1,
        },
 
+       /* ID 2 */
        {.name = "ipv4mc",
         .pattern = {0x01,0x00,0x5E},
         .pattern_len = 3,
@@ -8744,6 +8802,7 @@ static struct rx_filter rx_filters[] = {
         .mask_len = 1,
        },
 
+       /* ID 3 */
        {.name = "ipv6mc",
         .pattern = {0x33,0x33},
         .pattern_len = 2,
@@ -8751,18 +8810,45 @@ static struct rx_filter rx_filters[] = {
         .mask_len = 1,
        },
 
+       /* ID 4 */
        {.name = "dhcp",
-        .pattern = {0   , 0   , 0   , 0   , 0   , 0   , 0   , 0   ,
+        .pattern = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0   , 0   ,
                     0   , 0   , 0   , 0   , 0   , 0   , 0x45, 0   ,
                     0   , 0   , 0   , 0   , 0   , 0   , 0   , 0x11,
                     0   , 0   , 0   , 0   , 0   , 0   , 0   , 0   ,
                     0   , 0   , 0   , 0   , 0x00, 0x44},
         .pattern_len = 38,
-        .mask = { 0,                                 /* OCTET 1 */
-                  BIT(6),                            /* OCTET 2 */
-                  BIT(7),                            /* OCTET 3 */
-                  0,                                 /* OCTET 4 */
-                  BIT(4) | BIT(5) },                 /* OCTET 5 */
+        .mask = { BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
+                  BIT(6),                               /* OCTET 2 */
+                  BIT(7),                               /* OCTET 3 */
+                  0,                                    /* OCTET 4 */
+                  BIT(4) | BIT(5) },                    /* OCTET 5 */
+        .mask_len = 5,
+       },
+
+       /* ID 5 */
+       {.name = "arp",
+        .pattern = {0   , 0   , 0   , 0   , 0   , 0   , 0   , 0   ,
+                    0   , 0   , 0   , 0   , 0x08, 0x06},
+        .pattern_len = 14,
+        .mask = { 0,                                    /* OCTET 1 */
+                  BIT(4) | BIT(5) },                    /* OCTET 2 */
+        .mask_len = 2,
+       },
+
+       /* ID 6 */
+       {.name = "ssdp",
+        .pattern = {0x01, 0x00, 0x5E, 0   , 0   , 0   , 0   , 0   ,
+                    0   , 0   , 0   , 0   , 0   , 0   , 0x45, 0   ,
+                    0   , 0   , 0   , 0   , 0   , 0   , 0   , 0x11,
+                    0   , 0   , 0   , 0   , 0   , 0   , 0xEF, 0xFF,
+                    0xFF, 0xFA, 0   , 0   , 0x07, 0x6C},
+        .pattern_len = 38,
+        .mask = { BIT(0) | BIT(1) | BIT(2),             /* OCTET 1 */
+                  BIT(6),                               /* OCTET 2 */
+                  BIT(7),                               /* OCTET 3 */
+                  BIT(6) | BIT(7),                      /* OCTET 4 */
+                  BIT(0) | BIT(1) | BIT(4) | BIT(5) },  /* OCTET 5 */
         .mask_len = 5,
        },
 };
@@ -8802,10 +8888,13 @@ static int nl80211_set_wowlan_triggers(struct i802_bss *bss, int enable)
                        goto nla_put_failure;
                }
 
-               /* In ginger filter 0 and 1 are always set but in ICS they
-                  were completely removed. Make sure to always set them
-                  otherwise unicast and bcast are dropped */
-               filters = bss->drv->wowlan_triggers |= 3;
+               /*
+                * In GB filters 0 and 1 are always set but in ICS they
+                * were completely removed. Add filter 0 (unicast) by default
+                * so unicast traffic won't be dropped in any case.
+                */
+
+               filters = bss->drv->wowlan_triggers |= 1;
 
                for (i = 0; i < NR_RX_FILTERS; i++) {
                        struct rx_filter *rx_filter = &rx_filters[i];
@@ -8883,6 +8972,62 @@ static int nl80211_parse_wowlan_trigger_nr(char *s)
        return i;
 }
 
+static int nl80211_toggle_dropbcast(int enable)
+{
+       char filename[90];
+       int rv;
+       FILE *f;
+
+       snprintf(filename, sizeof(filename) - 1,
+                "/sys/bus/platform/devices/wl12xx/drop_bcast");
+       f = fopen(filename, "w");
+       if (!f) {
+               wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       rv = fprintf(f, "%d", enable);
+       fclose(f);
+       if (rv < 1) {
+               wpa_printf(MSG_DEBUG, "Could not write to file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+static int nl80211_dropbcast_get(char *buf, size_t buf_len)
+{
+       char filename[90], value[10], *pos;
+       int f, rv;
+
+       snprintf(filename, sizeof(filename) - 1,
+                "/sys/bus/platform/devices/wl12xx/drop_bcast");
+       f = open(filename, O_RDONLY);
+       if (f < 0) {
+               wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       rv = read(f, value, sizeof(value) - 1);
+       close(f);
+       if (rv < 0) {
+               wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
+                          filename, strerror(errno));
+               return -1;
+       }
+
+       value[rv] = '\0';
+       pos = os_strchr(value, '\n');
+       if (pos)
+               *pos = '\0';
+
+       return snprintf(buf, buf_len, "Drop bcast = %s\n", value);
+}
+
 #endif /* ANDROID */
 
 static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
@@ -9385,10 +9530,28 @@ static int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
                if(i < 0)
                        return i;
                return nl80211_toggle_wowlan_trigger(bss, i, 0);
-       } else if( os_strcasecmp(cmd, "RXFILTER-START") == 0 ) {
+       } else if (os_strcasecmp(cmd, "RXFILTER-START") == 0) {
                return nl80211_set_wowlan_triggers(bss, 1);
-       } else if( os_strcasecmp(cmd, "RXFILTER-STOP") == 0 ) {
+       } else if (os_strcasecmp(cmd, "RXFILTER-STOP") == 0) {
                return nl80211_set_wowlan_triggers(bss, 0);
+       } else if (os_strncasecmp(cmd, "DROPBCAST", 9) == 0) {
+               char *value = cmd + 10;
+
+               if (!os_strcasecmp(value, "ENABLE") ||
+                   !os_strcasecmp(value, "1")) {
+                       ret = nl80211_toggle_dropbcast(1);
+               } else if (!os_strcasecmp(value, "DISABLE") ||
+                          !os_strcasecmp(value, "0")) {
+                       ret = nl80211_toggle_dropbcast(0);
+               } else if (!os_strcasecmp(value, "GET") ||
+                          !os_strlen(value)) {
+                       ret = nl80211_dropbcast_get(buf, buf_len);
+               } else {
+                       wpa_printf(MSG_ERROR,
+                                  "Invalid parameter for DROPBCAST: %s",
+                                  value);
+                       ret = -1;
+               }
        } else if( os_strcasecmp(cmd, "LINKSPEED") == 0 ) {
                struct wpa_signal_info sig;
                int linkspeed;
@@ -9565,6 +9728,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        wpa_driver_nl80211_cancel_remain_on_channel,
        .probe_req_report = wpa_driver_nl80211_probe_req_report,
        .deinit_ap = wpa_driver_nl80211_deinit_ap,
+       .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
        .resume = wpa_driver_nl80211_resume,
        .send_ft_action = nl80211_send_ft_action,
        .signal_monitor = nl80211_signal_monitor,