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:

Reply via email to