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 <anchao@xiaomi.com>
This commit is contained in:
parent
9c68064024
commit
2992b10fbb
4 changed files with 337 additions and 19 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue