diff mbox

[5/7] bcmdhd: Enable Ad-Hoc (IBSS) mode

Message ID 1374259829-31388-1-git-send-email-ricardo.salveti@canonical.com
State New
Headers show

Commit Message

Ricardo Salveti de Araujo July 19, 2013, 6:50 p.m. UTC
From: Bruno Randolf <br1@einfach.org>

This enables Ad-Hoc (IBSS) mode for bcmdhd. We basically just need to set the
interface flag and avoid some P2P specific settings while scanning.

Also add the "station get" command for IBSS mode.

Signed-off-by: Bruno Randolf <br1@einfach.org>

Change-Id: I10a047f76495d7fedfee16d0ac10de239e494567
Signed-off-by: Ricardo Salveti de Araujo <ricardo.salveti@canonical.com>

 1 file changed, 63 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 2f28bf1..2796352 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -1614,7 +1614,7 @@  __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 					WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
 					p2p_scan(wl) = true;
 				}
-			} else {
+			} else if (wl_get_mode_by_netdev(wl, ndev) != WL_MODE_IBSS) {
 				/* legacy scan trigger
 				 * So, we have to disable p2p discovery if p2p discovery is on
 				 */
@@ -3064,7 +3064,68 @@  get_station_err:
 			wl_link_down(wl);
 		}
 	}
+	else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) {
+		u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
+
+		memset(&scb_val, 0, sizeof(scb_val));
+		bcopy(mac, &scb_val.ea, 6);
+
+		err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
+			sizeof(scb_val_t), false);
+		if (err) {
+			WL_ERR(("Could not get rssi (%d)\n", err));
+			return err;
+		}
+		rssi = dtoh32(scb_val.val);
+
+		/* the RSSI value from the firmware is an average but user-space
+		 expects it as signal, so we fill in both */
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = rssi;
+		sinfo->filled |= STATION_INFO_SIGNAL_AVG;
+		sinfo->signal_avg = rssi;
+
+		if (!memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
+			// BSSID is not a real station. Can't get sta_info; Done
+			return 0;
+		}
 
+		err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
+			ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
+		if (err < 0) {
+			WL_ERR(("GET STA INFO failed, %d\n", err));
+			return err;
+		}
+
+		sta = (sta_info_t *)wl->ioctl_buf;
+		sta->len = dtoh16(sta->len);
+		sta->cap = dtoh16(sta->cap);
+		sta->flags = dtoh32(sta->flags);
+		sta->idle = dtoh32(sta->idle);
+		sta->in = dtoh32(sta->in);
+		sta->listen_interval_inms = dtoh32(sta->listen_interval_inms);
+		sta->tx_pkts = dtoh32(sta->tx_pkts);
+		sta->tx_failures = dtoh32(sta->tx_failures);
+		sta->rx_ucast_pkts = dtoh32(sta->rx_ucast_pkts);
+		sta->rx_mcast_pkts = dtoh32(sta->rx_mcast_pkts);
+		sta->tx_rate = dtoh32(sta->tx_rate);
+		sta->rx_rate = dtoh32(sta->rx_rate);
+		sta->rx_decrypt_succeeds = dtoh32(sta->rx_decrypt_succeeds);
+		sta->rx_decrypt_failures = dtoh32(sta->rx_decrypt_failures);
+
+		sinfo->filled |= STATION_INFO_INACTIVE_TIME | STATION_INFO_TX_PACKETS |
+				STATION_INFO_TX_FAILED | STATION_INFO_RX_PACKETS |
+				STATION_INFO_TX_BITRATE | STATION_INFO_RX_BITRATE |
+				STATION_INFO_RX_DROP_MISC;
+
+		sinfo->inactive_time = sta->idle * 1000;
+		sinfo->tx_packets = sta->tx_pkts;
+		sinfo->tx_failed = sta->tx_failures;
+		sinfo->rx_packets = sta->rx_ucast_pkts + sta->rx_mcast_pkts;
+		sinfo->txrate.legacy = sta->tx_rate / 100;
+		sinfo->rxrate.legacy = sta->rx_rate / 100;
+		sinfo->rx_dropped_misc = sta->rx_decrypt_failures;
+	}
 	return err;
 }
 
@@ -4649,7 +4710,7 @@  static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
 	wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
 #endif /* WL_SCHED_SCAN */
 	wdev->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION)
+		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC)
 		| BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
 
 	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;