mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 12:08:36 +08:00
drivers/net: Add wireless ops in upper-half driver
Take the idea from Linux's iw_handler array and esp32c3_wlan's wlan_ops_s, and make it a common logic of upper-half driver. Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
parent
a7a47621fa
commit
c253bb91a2
3 changed files with 313 additions and 2 deletions
|
@ -45,6 +45,13 @@ config NETDEV_WORK_THREAD_PRIORITY
|
|||
---help---
|
||||
The priority of work poll thread in netdev.
|
||||
|
||||
config NETDEV_WIRELESS_HANDLER
|
||||
bool "Support wireless handler in upper-half driver"
|
||||
default y
|
||||
depends on NETDEV_IOCTL
|
||||
---help---
|
||||
Enable the wireless handler support in upper-half driver.
|
||||
|
||||
comment "General Ethernet MAC Driver Options"
|
||||
|
||||
config NET_RPMSG_DRV
|
||||
|
|
|
@ -537,6 +537,250 @@ static int netdev_upper_txavail(FAR struct net_driver_s *dev)
|
|||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netdev_upper_wireless_ioctl
|
||||
*
|
||||
* Description:
|
||||
* Support for wireless handlers in ioctl.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETDEV_WIRELESS_HANDLER
|
||||
int netdev_upper_wireless_ioctl(FAR struct netdev_lowerhalf_s *lower,
|
||||
int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -ENOTTY; /* Default to ENOTTY to indicate not serving. */
|
||||
FAR struct iwreq *iwr = (FAR struct iwreq *)arg;
|
||||
FAR const struct wireless_ops_s *ops = lower->iw_ops;
|
||||
const struct ether_addr zero =
|
||||
{
|
||||
};
|
||||
|
||||
/* Decode and dispatch the driver-specific IOCTL command */
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case SIOCSIWENCODEEXT: /* Set encoding token & mode */
|
||||
if (ops->passwd)
|
||||
{
|
||||
ret = ops->passwd(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWENCODEEXT: /* Get encoding token & mode */
|
||||
if (ops->passwd)
|
||||
{
|
||||
ret = ops->passwd(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWESSID: /* Set ESSID */
|
||||
if (ops->essid)
|
||||
{
|
||||
if ((iwr->u.essid.flags == IW_ESSID_ON) ||
|
||||
(iwr->u.essid.flags == IW_ESSID_DELAY_ON))
|
||||
{
|
||||
ret = ops->essid(lower, iwr, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (iwr->u.essid.flags == IW_ESSID_ON)
|
||||
{
|
||||
ret = ops->connect(lower);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to connect\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ops->disconnect(lower);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to disconnect\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWESSID: /* Get ESSID */
|
||||
if (ops->essid)
|
||||
{
|
||||
ret = ops->essid(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWAP: /* Set access point MAC addresses */
|
||||
if (ops->bssid)
|
||||
{
|
||||
if (memcmp(iwr->u.ap_addr.sa_data, &zero, sizeof(zero)) != 0)
|
||||
{
|
||||
ret = ops->bssid(lower, iwr, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to set BSSID\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ops->connect(lower);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to connect\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ops->disconnect(lower);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to disconnect\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWAP: /* Get access point MAC addresses */
|
||||
if (ops->bssid)
|
||||
{
|
||||
ret = ops->bssid(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWSCAN: /* Trigger scanning */
|
||||
if (ops->scan)
|
||||
{
|
||||
ret = ops->scan(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWSCAN: /* Get scanning results */
|
||||
if (ops->scan)
|
||||
{
|
||||
ret = ops->scan(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWCOUNTRY: /* Set country code */
|
||||
if (ops->country)
|
||||
{
|
||||
ret = ops->country(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWCOUNTRY: /* Get country code */
|
||||
if (ops->country)
|
||||
{
|
||||
ret = ops->country(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWSENS: /* Set sensitivity (dBm) */
|
||||
if (ops->sensitivity)
|
||||
{
|
||||
ret = ops->sensitivity(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWSENS: /* Get sensitivity (dBm) */
|
||||
if (ops->sensitivity)
|
||||
{
|
||||
ret = ops->sensitivity(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWMODE: /* Set operation mode */
|
||||
if (ops->mode)
|
||||
{
|
||||
ret = ops->mode(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWMODE: /* Get operation mode */
|
||||
if (ops->mode)
|
||||
{
|
||||
ret = ops->mode(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWAUTH: /* Set authentication mode params */
|
||||
if (ops->auth)
|
||||
{
|
||||
ret = ops->auth(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWAUTH: /* Get authentication mode params */
|
||||
if (ops->auth)
|
||||
{
|
||||
ret = ops->auth(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWFREQ: /* Set channel/frequency (MHz) */
|
||||
if (ops->freq)
|
||||
{
|
||||
ret = ops->freq(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWFREQ: /* Get channel/frequency (MHz) */
|
||||
if (ops->freq)
|
||||
{
|
||||
ret = ops->freq(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWRATE: /* Set default bit rate (Mbps) */
|
||||
if (ops->bitrate)
|
||||
{
|
||||
ret = ops->bitrate(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWRATE: /* Get default bit rate (Mbps) */
|
||||
if (ops->bitrate)
|
||||
{
|
||||
ret = ops->bitrate(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSIWTXPOW: /* Set transmit power (dBm) */
|
||||
if (ops->txpower)
|
||||
{
|
||||
ret = ops->txpower(lower, iwr, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWTXPOW: /* Get transmit power (dBm) */
|
||||
if (ops->txpower)
|
||||
{
|
||||
ret = ops->txpower(lower, iwr, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGIWRANGE: /* Get range of parameters */
|
||||
if (ops->range)
|
||||
{
|
||||
ret = ops->range(lower, iwr);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NETDEV_WIRELESS_HANDLER */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: netdev_upper_ifup/ifdown/addmac/rmmac/ioctl
|
||||
*
|
||||
|
@ -632,10 +876,22 @@ static int netdev_upper_ioctl(FAR struct net_driver_s *dev, int cmd,
|
|||
unsigned long arg)
|
||||
{
|
||||
FAR struct netdev_upperhalf_s *upper = dev->d_private;
|
||||
FAR struct netdev_lowerhalf_s *lower = upper->lower;
|
||||
|
||||
if (upper->lower->ops->ioctl)
|
||||
#ifdef CONFIG_NETDEV_WIRELESS_HANDLER
|
||||
if (lower->iw_ops)
|
||||
{
|
||||
return upper->lower->ops->ioctl(upper->lower, cmd, arg);
|
||||
int ret = netdev_upper_wireless_ioctl(lower, cmd, arg);
|
||||
if (ret != -ENOTTY)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lower->ops->ioctl)
|
||||
{
|
||||
return lower->ops->ioctl(lower, cmd, arg);
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <nuttx/net/ip.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/wireless/wireless.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
|
@ -87,10 +88,17 @@ enum netpkt_type_e
|
|||
*/
|
||||
|
||||
struct netdev_ops_s;
|
||||
struct wireless_ops_s;
|
||||
struct netdev_lowerhalf_s
|
||||
{
|
||||
FAR const struct netdev_ops_s *ops;
|
||||
|
||||
/* Extended operations. */
|
||||
|
||||
#ifdef CONFIG_NETDEV_WIRELESS_HANDLER
|
||||
FAR const struct wireless_ops_s *iw_ops;
|
||||
#endif
|
||||
|
||||
/* Max # of buffer held by driver */
|
||||
|
||||
#ifdef CONFIG_HAVE_ATOMICS
|
||||
|
@ -148,6 +156,46 @@ struct netdev_ops_s
|
|||
#endif
|
||||
};
|
||||
|
||||
/* This structure is a set of wireless handlers, leave unsupported operations
|
||||
* as NULL is OK.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NETDEV_WIRELESS_HANDLER
|
||||
typedef int (*iw_handler_rw)(FAR struct netdev_lowerhalf_s *dev,
|
||||
FAR struct iwreq *iwr, bool set);
|
||||
typedef int (*iw_handler_ro)(FAR struct netdev_lowerhalf_s *dev,
|
||||
FAR struct iwreq *iwr);
|
||||
|
||||
struct wireless_ops_s
|
||||
{
|
||||
/* Connect / disconnect operation, should exist if essid or bssid exists */
|
||||
|
||||
int (*connect)(FAR struct netdev_lowerhalf_s *dev);
|
||||
int (*disconnect)(FAR struct netdev_lowerhalf_s *dev);
|
||||
|
||||
/* The following attributes need both set and get. */
|
||||
|
||||
iw_handler_rw essid;
|
||||
iw_handler_rw bssid;
|
||||
iw_handler_rw passwd;
|
||||
iw_handler_rw mode;
|
||||
iw_handler_rw auth;
|
||||
iw_handler_rw freq;
|
||||
iw_handler_rw bitrate;
|
||||
iw_handler_rw txpower;
|
||||
iw_handler_rw country;
|
||||
iw_handler_rw sensitivity;
|
||||
|
||||
/* Scan operation: start scan (set=1) / get scan result (set=0). */
|
||||
|
||||
iw_handler_rw scan;
|
||||
|
||||
/* Get-only attributes. */
|
||||
|
||||
iw_handler_ro range;
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
|
Loading…
Reference in a new issue