This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 2992b10fbb wireless/bcm43xxx: add more ioctl command support
2992b10fbb is described below
commit 2992b10fbb4b558705796dfde6268c0b082dbe22
Author: chao.an <[email protected]>
AuthorDate: Fri Jun 17 14:47:26 2022 +0800
wireless/bcm43xxx: add more ioctl command support
Support command:
SIOCGIWFREQ
SIOCGIWMODE
SIOCSIWAP
SIOCGIWAP
SIOCGIWESSID
SIOCGIWRATE
SIOCGIWTXPOW
SIOCGIWSENS
SIOCGIWRANGE
Before: After:
cp> wapi show wlan0 cp> wapi show wlan0
wlan0 Configuration: wlan0 Configuration:
IP: 192.168.31.202 IP: 192.168.31.202
NetMask: 255.255.255.0 NetMask: 255.255.255.0
ioctl(SIOCGIWFREQ): 88 Frequency: 5785
ERROR: wapi_get_freq() failed: -88 Flag: WAPI_FREQ_AUTO
ioctl(SIOCGIWESSID): 88 Channel: 157
ERROR: wapi_get_essid() failed: -88 Frequency: 5785
ioctl(SIOCGIWMODE): 88 ESSID: archer5
ERROR: wapi_get_mode() failed: -88 Flag: WAPI_ESSID_ON
ioctl(SIOCGIWAP): 88 Mode: WAPI_MODE_MANAGED
ERROR: wapi_get_ap() failed: -88 AP: ec:41:18:e0:76:7f
ioctl(SIOCGIWRATE): 88 BitRate: 58500
ERROR: wapi_get_bitrate() failed: -88 Flag: WAPI_BITRATE_FIXED
ioctl(SIOCGIWTXPOW): 88 TxPower: 31
ERROR: wapi_get_txpower() failed: -88 Flag: WAPI_TXPOWER_DBM
ioctl(SIOCGIWSENS): 25 Sense: -17
Signed-off-by: chao.an <[email protected]>
---
drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c | 305 +++++++++++++++++++++-
drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h | 15 ++
drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h | 7 +
drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c | 29 +-
4 files changed, 337 insertions(+), 19 deletions(-)
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
index ba97bb5733..c477cfc7a7 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c
@@ -155,6 +155,32 @@ static int bcmf_wl_get_interface(FAR struct bcmf_dev_s
*priv,
* Private Functions
****************************************************************************/
+static int bcmf_wl_channel_to_frequency(int chan)
+{
+ if (chan <= 0)
+ {
+ return 0;
+ }
+ else if (chan < 14)
+ {
+ return 2407 + chan * 5;
+ }
+ else if (chan == 14)
+ {
+ return 2484;
+ }
+ else if ((chan >= 36) && (chan <= 165))
+ {
+ return 5000 + chan * 5;
+ }
+ else if ((chan >= 182) && (chan <= 196))
+ {
+ return 4000 + chan * 5;
+ }
+
+ return 0; /* not supported */
+}
+
FAR struct bcmf_dev_s *bcmf_allocate_device(void)
{
int ret;
@@ -1358,9 +1384,9 @@ int bcmf_wl_set_auth_param(FAR struct bcmf_dev_s *priv,
struct iwreq *iwr)
int bcmf_wl_set_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
- int interface;
uint32_t out_len;
uint32_t value;
+ int interface;
interface = bcmf_wl_get_interface(priv, iwr);
@@ -1369,17 +1395,257 @@ int bcmf_wl_set_mode(FAR struct bcmf_dev_s *priv,
struct iwreq *iwr)
return -EINVAL;
}
- out_len = 4;
+ out_len = sizeof(value);
value = iwr->u.mode == IW_MODE_INFRA ? 1 : 0;
- if (bcmf_cdc_ioctl(priv, interface, true,
- WLC_SET_INFRA, (uint8_t *)&value, &out_len))
+
+ return bcmf_cdc_ioctl(priv, interface, true,
+ WLC_SET_INFRA, (uint8_t *)&value, &out_len);
+}
+
+int bcmf_wl_get_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ uint32_t out_len;
+ uint32_t infra;
+ int interface;
+ uint32_t ap;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
{
- return -EIO;
+ return -EINVAL;
+ }
+
+ out_len = sizeof(infra);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_INFRA, (uint8_t *)&infra, &out_len);
+ if (ret == OK)
+ {
+ out_len = sizeof(ap);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_AP, (uint8_t *)&ap, &out_len);
+ }
+
+ if (ret == OK)
+ {
+ if (infra == 0)
+ {
+ iwr->u.mode = IW_MODE_ADHOC;
+ }
+ else if (ap)
+ {
+ iwr->u.mode = IW_MODE_MASTER;
+ }
+ else
+ {
+ iwr->u.mode = IW_MODE_INFRA;
+ }
+ }
+
+ return ret;
+}
+
+int bcmf_wl_set_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ uint32_t out_len;
+ int interface;
+ int ap = 0;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ out_len = sizeof(ap);
+ ret = bcmf_cdc_ioctl(priv, interface, false, WLC_GET_AP,
+ (uint8_t *)&ap, &out_len);
+ if (ret == OK)
+ {
+ out_len = sizeof(struct ether_addr);
+ ret = bcmf_cdc_ioctl(priv, interface, true,
+ (ap ? WLC_SET_BSSID : WLC_REASSOC),
+ (uint8_t *)iwr->u.ap_addr.sa_data, &out_len);
+ }
+
+ return ret;
+}
+
+int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ uint32_t out_len;
+ int interface;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ iwr->u.ap_addr.sa_family = ARPHRD_ETHER;
+ out_len = sizeof(struct ether_addr);
+
+ return bcmf_cdc_ioctl(priv, interface, false, WLC_GET_BSSID,
+ (uint8_t *)iwr->u.ap_addr.sa_data, &out_len);
+}
+
+int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ channel_info_t ci;
+ uint32_t out_len;
+ int interface;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ out_len = sizeof(ci);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_CHANNEL, (uint8_t *)&ci, &out_len);
+ if (ret == OK)
+ {
+ iwr->u.freq.m = bcmf_wl_channel_to_frequency(ci.target_channel);
+ }
+
+ return ret;
+}
+
+int bcmf_wl_get_rate(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ uint32_t out_len;
+ uint32_t rate;
+ int interface;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ out_len = sizeof(rate);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_RATE, (uint8_t *)&rate, &out_len);
+ if (ret == OK)
+ {
+ iwr->u.bitrate.value = ((rate / 2) * 1000) + ((rate & 1) ? 500 : 0);
+ iwr->u.bitrate.fixed = 1;
+ }
+
+ return ret;
+}
+
+int bcmf_wl_get_txpower(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ uint32_t out_len;
+ int interface;
+ int radio;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ out_len = sizeof(radio);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_RADIO, (uint8_t *)&radio, &out_len);
+ if (ret == OK)
+ {
+ out_len = sizeof(iwr->u.txpower.value);
+ ret = bcmf_cdc_iovar_request(priv, interface, false,
+ IOVAR_STR_QTXPOWER,
+ (uint8_t *)&(iwr->u.txpower.value),
+ &out_len);
+ if (ret == OK)
+ {
+ iwr->u.txpower.value &= ~WL_TXPWR_OVERRIDE;
+ iwr->u.txpower.value /= 4;
+
+ iwr->u.txpower.fixed = 0;
+ iwr->u.txpower.disabled = radio;
+ iwr->u.txpower.flags = IW_TXPOW_DBM;
+ }
+ }
+
+ return ret;
+}
+
+int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ struct iw_range *range;
+ channel_info_t ci;
+ uint32_t out_len;
+ int interface;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ if (iwr->u.data.length < sizeof(struct iw_range))
+ {
+ return -EINVAL;
+ }
+
+ range = iwr->u.data.pointer;
+
+ memset(range, 0, sizeof(*range));
+
+ out_len = sizeof(ci);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_CHANNEL, (uint8_t *)&ci, &out_len);
+ if (ret == OK)
+ {
+ range->num_frequency = 1;
+ range->freq[0].m = bcmf_wl_channel_to_frequency(ci.target_channel);
+ range->freq[0].i = ci.target_channel;
}
return OK;
}
+int bcmf_wl_get_rssi(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ wl_sta_rssi_t rssi;
+ uint32_t out_len;
+ int interface;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ memset(&rssi.sta_addr, 0x0, sizeof(rssi.sta_addr));
+
+ out_len = sizeof(rssi);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_RSSI, (uint8_t *)&rssi, &out_len);
+ if (ret == OK)
+ {
+ iwr->u.sens.value = -rssi.rssi;
+ }
+
+ return ret;
+}
+
int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
int interface;
@@ -1468,3 +1734,32 @@ int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct
iwreq *iwr)
return OK;
}
+
+int bcmf_wl_get_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
+{
+ uint32_t out_len;
+ wlc_ssid_t ssid;
+ int interface;
+ int ret;
+
+ interface = bcmf_wl_get_interface(priv, iwr);
+
+ if (interface < 0)
+ {
+ return -EINVAL;
+ }
+
+ /* Configure AP SSID and trig authentication request */
+
+ out_len = sizeof(ssid);
+ ret = bcmf_cdc_ioctl(priv, interface, false,
+ WLC_GET_SSID, (uint8_t *)&ssid, &out_len);
+ if (ret == OK)
+ {
+ iwr->u.essid.flags = iwr->u.data.flags = 1;
+ iwr->u.essid.length = iwr->u.data.length = ssid.ssid_len + 1;
+ memcpy(iwr->u.essid.pointer, ssid.SSID, iwr->u.essid.length);
+ }
+
+ return ret;
+}
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
index 4386e4624e..3a5c96d63e 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
@@ -151,7 +151,22 @@ int bcmf_wl_set_auth_param(FAR struct bcmf_dev_s *priv,
struct iwreq *iwr);
int bcmf_wl_set_encode_ext(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+int bcmf_wl_get_mode(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
int bcmf_wl_set_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+int bcmf_wl_get_ssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+
+int bcmf_wl_set_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+int bcmf_wl_get_bssid(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+
+int bcmf_wl_get_channel(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+
+int bcmf_wl_get_rate(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+
+int bcmf_wl_get_txpower(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+
+int bcmf_wl_get_rssi(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
+
+int bcmf_wl_get_iwrange(FAR struct bcmf_dev_s *priv, struct iwreq *iwr);
#endif /* __DRIVERS_WIRELESS_IEEE80211_BCM43XXX_BCMF_DRIVER_H */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
b/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
index d57b463598..959fb294c0 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_ioctl.h
@@ -2712,6 +2712,13 @@ typedef struct wl_rssi_event
int8_t rssi_levels[MAX_RSSI_LEVELS];
} wl_rssi_event_t;
+typedef struct wl_sta_rssi
+{
+ uint32_t rssi;
+ struct ether_addr sta_addr;
+ uint16_t foo;
+} wl_sta_rssi_t;
+
#define WLFEATURE_DISABLE_11N 0x00000001
#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002
#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
index 1a87db2c47..acae29d492 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
@@ -915,8 +915,7 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
break;
case SIOCGIWFREQ: /* Get channel/frequency (Hz) */
- wlwarn("WARNING: SIOCGIWFREQ not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_get_channel(priv, (struct iwreq *)arg);
break;
case SIOCSIWMODE: /* Set operation mode */
@@ -924,18 +923,15 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int
cmd,
break;
case SIOCGIWMODE: /* Get operation mode */
- wlwarn("WARNING: SIOCGIWMODE not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_get_mode(priv, (struct iwreq *)arg);
break;
case SIOCSIWAP: /* Set access point MAC addresses */
- wlwarn("WARNING: SIOCSIWAP not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_set_bssid(priv, (struct iwreq *)arg);
break;
case SIOCGIWAP: /* Get access point MAC addresses */
- wlwarn("WARNING: SIOCGIWAP not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_get_bssid(priv, (struct iwreq *)arg);
break;
case SIOCSIWESSID: /* Set ESSID (network name) */
@@ -943,8 +939,7 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
break;
case SIOCGIWESSID: /* Get ESSID */
- wlwarn("WARNING: SIOCGIWESSID not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_get_ssid(priv, (struct iwreq *)arg);
break;
case SIOCSIWRATE: /* Set default bit rate (bps) */
@@ -953,8 +948,7 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
break;
case SIOCGIWRATE: /* Get default bit rate (bps) */
- wlwarn("WARNING: SIOCGIWRATE not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_get_rate(priv, (struct iwreq *)arg);
break;
case SIOCSIWTXPOW: /* Set transmit power (dBm) */
@@ -963,8 +957,15 @@ static int bcmf_ioctl(FAR struct net_driver_s *dev, int
cmd,
break;
case SIOCGIWTXPOW: /* Get transmit power (dBm) */
- wlwarn("WARNING: SIOCGIWTXPOW not implemented\n");
- ret = -ENOSYS;
+ ret = bcmf_wl_get_txpower(priv, (struct iwreq *)arg);
+ break;
+
+ case SIOCGIWSENS: /* Get transmit power (dBm) */
+ ret = bcmf_wl_get_rssi(priv, (struct iwreq *)arg);
+ break;
+
+ case SIOCGIWRANGE: /* Get range of parameters */
+ ret = bcmf_wl_get_iwrange(priv, (struct iwreq *)arg);
break;
default: