index c392b2a18f4d7f9591c040a5eb5dc8be57d3dcf1..fd9b082a2940f4f0964611f605c5e7fa8fea0bdd 100644 (file)
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;
}
+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)
{
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,
* 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;
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) {
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);
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)
{
}
static struct rx_filter rx_filters[] = {
+ /* ID 0 */
{.name = "self",
.pattern = {},
.pattern_len = 6,
.get_pattern_handler = nl80211_self_filter_get_pattern_handler,
},
+ /* ID 1 */
{.name = "bcast",
.pattern = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
.pattern_len = 6,
.mask_len = 1,
},
+ /* ID 2 */
{.name = "ipv4mc",
.pattern = {0x01,0x00,0x5E},
.pattern_len = 3,
.mask_len = 1,
},
+ /* ID 3 */
{.name = "ipv6mc",
.pattern = {0x33,0x33},
.pattern_len = 2,
.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,
},
};
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];
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 < 0) {
+ 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)
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;
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,