Networking: Add support for some packet radio IOCTL commands; Spirit: Fix a few bugs from testing.

This commit is contained in:
Gregory Nutt 2017-08-02 11:52:44 -06:00
parent 42b3ee4cfc
commit 1ae9748170
8 changed files with 340 additions and 20 deletions

View File

@ -68,6 +68,7 @@ CONFIG_NSH_DISABLE_PUT=y
CONFIG_NSH_DISABLE_WGET=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_NETLOCAL=y
CONFIG_NSH_NOMAC=y
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_MQ_MSGS=4

View File

@ -1566,19 +1566,92 @@ static int spirit_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac)
static int spirit_ioctl(FAR struct net_driver_s *dev, int cmd,
unsigned long arg)
{
FAR struct spirit_driver_s *priv = (FAR struct spirit_driver_s *)dev->d_private;
int ret;
FAR struct pktradio_ifreq_s *cmddata;
FAR struct spirit_driver_s *priv;
int ret = -ENOTTY;
/* Decode and dispatch the driver-specific IOCTL command */
DEBUGASSERT(dev != NULL && dev->d_private != NULL && arg != 0ul);
priv = (FAR struct spirit_driver_s *)dev->d_private;
cmddata = (FAR struct pktradio_ifreq_s *)((uintptr_t)arg);
spirit_lock(priv);
switch (cmd)
{
/* Add cases here to support the IOCTL commands */
/* SIOCPKTRADIOGGPROPS
* Description: Get the radio properties
* Input: Pointer to read-write instance of struct
* pktradio_ifreq_s
* Output: Properties returned in struct pktradio_ifreq_s
* instance
*/
case SIOCPKTRADIOGGPROPS:
{
FAR struct sixlowpan_driver_s *radio =
(FAR struct sixlowpan_driver_s *)dev;
FAR struct sixlowpan_properties_s *props =
(FAR struct sixlowpan_properties_s *)&cmddata->pifr_props;
ret = spirit_properties(radio, props);
}
break;
/* SIOCPKTRADIOSNODE
* Description: Set the radio node address
* Input: Pointer to read-only instance of struct
* pktradio_ifreq_s
* Output: None
*/
case SIOCPKTRADIOSNODE:
{
FAR const struct pktradio_addr_s *newaddr =
(FAR const struct pktradio_addr_s *)&cmddata->pifr_hwaddr;
if (newaddr->pa_addrlen != 1)
{
ret = -EINVAL;
}
else
{
FAR struct netdev_varaddr_s *devaddr = &dev->d_mac.sixlowpan;
devaddr->nv_addrlen = 1;
devaddr->nv_addr[0] = newaddr->pa_addr[0];
#if CONFIG_PKTRADIO_ADDRLEN > 1
memset(&devaddr->pa_addr[1], 0, CONFIG_PKTRADIO_ADDRLEN - 1);
#endif
ret = OK;
}
}
break;
/* SIOCPKTRADIOGNODE
* Description: Get the radio node address
* Input: Pointer to read-write instance of
* struct pktradio_ifreq_s
* Output: Node address return in struct pktradio_ifreq_s
* instance
*/
case SIOCPKTRADIOGNODE:
{
FAR struct pktradio_addr_s *retaddr =
(FAR struct pktradio_addr_s *)&cmddata->pifr_hwaddr;
FAR struct netdev_varaddr_s *devaddr = &dev->d_mac.sixlowpan;
retaddr->pa_addrlen = devaddr->nv_addrlen;
retaddr->pa_addr[0] = devaddr->nv_addr[0];
#if CONFIG_PKTRADIO_ADDRLEN > 1
memset(&addr->pa_addr[1], 0, CONFIG_PKTRADIO_ADDRLEN - 1);
#endif
ret = OK;
}
break;
default:
wlerr("ERROR: Unrecognized IOCTL command: %02x\n", cmd);
ret = -ENOTTY; /* Special return value for this case */
wlwarn("WARNING: Unrecognized IOCTL command: %02x\n", cmd);
break;
}
spirit_unlock(priv);

View File

@ -41,6 +41,7 @@
#include <sys/types.h>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#include <assert.h>
#include <errno.h>

View File

@ -44,6 +44,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/wireless/wireless.h>
#ifdef CONFIG_WIRELESS_PKTRADIO
@ -51,6 +52,36 @@
* Pre-processor Definitions
****************************************************************************/
/* Packet radio network device IOCTL commands. */
#ifndef WL_NPKTRADIOCMDS != 3
# error Incorrect setting for number of PktRadio IOCTL commands
#endif
/* SIOCPKTRADIOGGPROPS
* Description: Get the radio properties
* Input: Pointer to read-write instance of struct pktradio_ifreq_s
* Output: Properties returned in struct pktradio_ifreq_s instance
*/
#define SIOCPKTRADIOGGPROPS _WLIOC(WL_PKTRADIOFIRST)
/* SIOCPKTRADIOGSNODE
* Description: Set the radio node address
* Input: Pointer to read-only instance of struct pktradio_ifreq_s
* Output: None
*/
#define SIOCPKTRADIOSNODE _WLIOC(WL_PKTRADIOFIRST + 1)
/* SIOCPKTRADIOGGNODE
* Description: Get the radio node address
* Input: Pointer to read-write instance of struct pktradio_ifreq_s
* Output: Node address return in struct pktradio_ifreq_s instance
*/
#define SIOCPKTRADIOGNODE _WLIOC(WL_PKTRADIOFIRST + 2)
/* Memory Pools */
#define PKTRADIO_POOL_PREALLOCATED 0
@ -60,8 +91,6 @@
* Public Types
****************************************************************************/
struct iob_s; /* Forward reference */
/* This describes an address used by the packet radio. There is no standard
* size for such an address. Hence, it is represented simply as a arry of
* bytes.
@ -73,10 +102,45 @@ struct pktradio_addr_s
uint8_t pa_addr[CONFIG_PKTRADIO_ADDRLEN];
};
/* Different packet radios may have different properties. If there are
* multiple packet radios, then those properties have to be queried at
* run time. This information is provided to the 6LoWPAN network via the
* following structure.
*
* NOTE: This MUST be the same as the struct sixlowpan_properties_s as
* defined in sixlowpan.h. It is duplicated here with a different name in
* order to avoid circular header file inclusion.
*/
struct pktradio_properties_s
{
uint8_t pp_addrlen; /* Length of an address */
uint8_t pp_pktlen; /* Fixed packet/frame size (up to 255) */
};
/* This is the structure passed with all packet radio IOCTL commands.
* NOTE: This is merely a placeholder for now.
*/
struct pktradio_ifreq_s
{
char pifr_name[IFNAMSIZ]; /* Network device name (e.g. "wpan0") */
union
{
struct pktradio_addr_s pifru_hwaddr; /* Radio node address */
struct pktradio_properties_s pifru_props; /* Radio properties */
} pifr_u;
};
#define pifr_hwaddr pifr_u.pifru_hwaddr /* Radio node address */
#define pifr_props pifr_u.pifru_props /* Radio properties */
/* This is the form of the meta data that provides the radio-specific
* information necessary to send and receive packets to and from the radio.
*/
struct iob_s; /* Forward reference */
struct pktradio_metadata_s
{
struct pktradio_metadata_s *pm_flink; /* Supports a singly linked list */

View File

@ -158,9 +158,25 @@
#define WL_NETFIRST 0x0001 /* First network command */
#define WL_NNETCMDS 0x0032 /* Number of network commands */
#define WL_USERFIRST (WL_NETFIRST + WL_NNETCMDS)
/* ----------------------- WIRELESS EVENTS ----------------------- */
/* Reserved for IEEE802.15.4 wireless network devices
* NOTE: Not used. Currently logic uses IOCTL commands from the IEEE802.15.4
* character driver space.
*/
#define WL_802154FIRST (WL_NETFIRST + WL_NNETCMDS)
#define WL_N802154CMDS (3)
#define WL_ISPKTRADIOCMD(cmd) ((cmd) >= WL_802154FIRST && \
(cmd) < (WL_802154FIRST + WL_N802154CMDS))
/* Reserved for network packet radio network devices */
#define WL_PKTRADIOFIRST (WL_802154FIRST + WL_N802154CMDS)
#define WL_NPKTRADIOCMDS (3)
#define WL_ISPKTRADIOCMD(cmd) ((cmd) >= WL_PKTRADIOFIRST && \
(cmd) < (WL_PKTRADIOFIRST + WL_NPKTRADIOCMDS))
/* ------------------------------- WIRELESS EVENTS ------------------------------- */
/* Those are *NOT* ioctls, do not issue request on them !!! */
/* Most events use the same identifier as ioctl requests */

View File

@ -73,7 +73,13 @@
#endif
#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NET_6LOWPAN)
# include <nuttx/wireless/ieee802154/ieee802154_mac.h>
# ifdef CONFIG_WIRELESS_IEEE802154
# include <nuttx/wireless/ieee802154/ieee802154_mac.h>
# endif
# ifdef CONFIG_WIRELESS_PKTRADIO
# include <nuttx/wireless/pktradio.h>
# endif
#endif
#include "arp/arp.h"
@ -342,7 +348,8 @@ static void ioctl_set_ipv6addr(FAR net_ipv6addr_t outaddr,
*
****************************************************************************/
#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NET_6LOWPAN)
#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NET_6LOWPAN) && \
defined(CONFIG_WIRELESS_IEEE802154)
static int netdev_iee802154_ioctl(FAR struct socket *psock, int cmd,
unsigned long arg)
{
@ -355,7 +362,7 @@ static int netdev_iee802154_ioctl(FAR struct socket *psock, int cmd,
if (_MAC802154IOCVALID(cmd))
{
/* Get the IEEE802.15.4 MAC device to receive the radio IOCTL
* commdand
* command
*/
FAR struct ieee802154_netmac_s *netmac =
@ -365,7 +372,7 @@ static int netdev_iee802154_ioctl(FAR struct socket *psock, int cmd,
}
else
{
/* The IOCTL command is neither */
/* Not an EEE802.15.4 MAC IOCTL command */
return -ENOTTY;
}
@ -373,7 +380,77 @@ static int netdev_iee802154_ioctl(FAR struct socket *psock, int cmd,
/* Find the device with this name */
dev = netdev_findbyname(ifname);
#ifdef CONFIG_NET_MULTILINK
if (dev != NULL && dev->d_lltype == NET_LL_IEEE802154)
#else
if (dev != NULL)
#endif
{
/* Perform the device IOCTL */
ret = dev->d_ioctl(dev, cmd, arg);
}
}
return ret;
}
#endif
/****************************************************************************
* Name: netdev_pktradio_ioctl
*
* Description:
* Perform non-IEEE802.15.4 packet radio network device specific operations.
*
* Parameters:
* psock Socket structure
* dev Ethernet driver device structure
* cmd The ioctl command
* req The argument of the ioctl cmd
*
* Return:
* >=0 on success (positive non-zero values are cmd-specific)
* Negated errno returned on failure.
*
****************************************************************************/
#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NET_6LOWPAN) && \
defined(CONFIG_WIRELESS_PKTRADIO)
static int netdev_pktradio_ioctl(FAR struct socket *psock, int cmd,
unsigned long arg)
{
FAR struct net_driver_s *dev;
FAR char *ifname;
int ret = -ENOTTY;
if (arg != 0ul)
{
if (WL_ISPKTRADIOCMD(cmd))
{
/* Get the packet radio device to receive the radio IOCTL
* command
*/
FAR struct pktradio_ifreq_s *cmddata =
(FAR struct pktradio_ifreq_s *)((uintptr_t)arg);
ifname = cmddata->pifr_name;
}
else
{
/* Not a packet radio IOCTL command */
return -ENOTTY;
}
/* Find the device with this name */
dev = netdev_findbyname(ifname);
#ifdef CONFIG_NET_MULTILINK
if (dev != NULL && dev->d_lltype == NET_LL_PKTRADIO)
#else
if (dev != NULL)
#endif
{
/* Perform the device IOCTL */
@ -1269,6 +1346,7 @@ int psock_ioctl(FAR struct socket *psock, int cmd, unsigned long arg)
#endif
#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NET_6LOWPAN)
#ifdef CONFIG_WIRELESS_IEEE802154
/* Check for a IEEE802.15.4 network device command */
if (ret == -ENOTTY)
@ -1276,6 +1354,15 @@ int psock_ioctl(FAR struct socket *psock, int cmd, unsigned long arg)
ret = netdev_iee802154_ioctl(psock, cmd, arg);
}
#endif
#ifdef CONFIG_WIRELESS_PKTRADIO
/* Check for a non-IEEE802.15.4 packet radio network device command */
if (ret == -ENOTTY)
{
ret = netdev_pktradio_ioctl(psock, cmd, arg);
}
#endif
#endif
#ifdef CONFIG_NET_IGMP
/* Check for address filtering commands */

View File

@ -726,16 +726,94 @@ static int lo_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac)
static int lo_ioctl(FAR struct net_driver_s *dev, int cmd,
unsigned long arg)
{
FAR struct pktradio_ifreq_s *cmddata;
FAR struct lo_driver_s *priv;
int ret = -ENOTTY;
DEBUGASSERT(dev != NULL && dev->d_private != NULL);
priv = (FAR struct lo_driver_s *)dev->d_private;
DEBUGASSERT(dev != NULL && dev->d_private != NULL && arg != 0ul);
priv = (FAR struct lo_driver_s *)dev->d_private;
cmddata = (FAR struct pktradio_ifreq_s *)((uintptr_t)arg);
UNUSED(priv);
switch (cmd)
{
/* SIOCPKTRADIOGGPROPS
* Description: Get the radio properties
* Input: Pointer to read-write instance of struct
* pktradio_ifreq_s
* Output: Properties returned in struct pktradio_ifreq_s
* instance
*/
/* Reserved for future use */
case SIOCPKTRADIOGGPROPS:
{
FAR struct sixlowpan_driver_s *radio =
(FAR struct sixlowpan_driver_s *)dev;
FAR struct sixlowpan_properties_s *props =
(FAR struct sixlowpan_properties_s *)&cmddata->pifr_props;
return -ENOTTY;
ret = spirit_properties(radio, props);
}
break;
/* SIOCPKTRADIOSNODE
* Description: Set the radio node address
* Input: Pointer to read-only instance of struct
* pktradio_ifreq_s
* Output: None
*/
case SIOCPKTRADIOSNODE:
{
FAR const struct pktradio_addr_s *newaddr =
(FAR const struct pktradio_addr_s *)&cmddata->pifr_hwaddr;
if (newaddr->pa_addrlen != 1)
{
ret = -EINVAL;
}
else
{
FAR const struct netdev_varaddr_s *devaddr = &dev->d_mac.sixlowpan;
devaddr->nv_addrlen = 1;
devaddr->nv_addr[0] = newaddr->pa_addr[0];
#if CONFIG_PKTRADIO_ADDRLEN > 1
memset(&devaddr->pa_addr[1], 0, CONFIG_PKTRADIO_ADDRLEN - 1);
#endif
ret = OK;
}
}
break;
/* SIOCPKTRADIOGNODE
* Description: Get the radio node address
* Input: Pointer to read-write instance of
* struct pktradio_ifreq_s
* Output: Node address return in struct pktradio_ifreq_s
* instance
*/
case SIOCPKTRADIOGNODE:
{
FAR struct pktradio_addr_s *retaddr =
(FAR struct pktradio_addr_s *)&cmddata->pifr_hwaddr;
FAR const struct netdev_varaddr_s *devaddr = &dev->d_mac.sixlowpan;
retaddr->pa_addrlen = devaddr->nv_addrlen;
retaddr->pa_addr[0] = devaddr->nv_addr[0];
#if CONFIG_PKTRADIO_ADDRLEN > 1
memset(&addr->pa_addr[1], 0, CONFIG_PKTRADIO_ADDRLEN - 1);
#endif
ret = OK;
}
break;
default:
wlwarn("WARNING: Unrecognized IOCTL command: %02x\n", cmd);
break;
}
return ret;
}
#endif

View File

@ -190,7 +190,7 @@ FAR struct pktradio_metadata_s *pktradio_metadata_allocate(void)
{
/* Zero and tag the alloated meta-data structure. */
memset(&metadata, 0, sizeof(struct pktradio_metadata_s));
memset(metadata, 0, sizeof(struct pktradio_metadata_s));
metadata->pm_pool = pool;
}