diff --git a/configs/b-l475e-iot01a/spirit-6lowpan/defconfig b/configs/b-l475e-iot01a/spirit-6lowpan/defconfig index b2537c314a..bdbda4cb0f 100644 --- a/configs/b-l475e-iot01a/spirit-6lowpan/defconfig +++ b/configs/b-l475e-iot01a/spirit-6lowpan/defconfig @@ -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 diff --git a/drivers/wireless/spirit/drivers/spirit_netdev.c b/drivers/wireless/spirit/drivers/spirit_netdev.c index 7bb4a9e55f..b871faf195 100644 --- a/drivers/wireless/spirit/drivers/spirit_netdev.c +++ b/drivers/wireless/spirit/drivers/spirit_netdev.c @@ -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); diff --git a/drivers/wireless/spirit/lib/spirit_radio.c b/drivers/wireless/spirit/lib/spirit_radio.c index f0141386de..b5dc649d9c 100644 --- a/drivers/wireless/spirit/lib/spirit_radio.c +++ b/drivers/wireless/spirit/lib/spirit_radio.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include diff --git a/include/nuttx/wireless/pktradio.h b/include/nuttx/wireless/pktradio.h index 3fd2a6a22e..26fa35a6e5 100644 --- a/include/nuttx/wireless/pktradio.h +++ b/include/nuttx/wireless/pktradio.h @@ -44,6 +44,7 @@ ****************************************************************************/ #include +#include #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 */ diff --git a/include/nuttx/wireless/wireless.h b/include/nuttx/wireless/wireless.h index 8bc0f5dcdf..238c526fa5 100644 --- a/include/nuttx/wireless/wireless.h +++ b/include/nuttx/wireless/wireless.h @@ -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 */ diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 46d001a729..fbefabe29f 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -73,7 +73,13 @@ #endif #if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NET_6LOWPAN) -# include +# ifdef CONFIG_WIRELESS_IEEE802154 +# include +# endif + +# ifdef CONFIG_WIRELESS_PKTRADIO +# include +# 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 */ diff --git a/wireless/pktradio/pktradio_loopback.c b/wireless/pktradio/pktradio_loopback.c index 8c6ad88eeb..b04a26640d 100644 --- a/wireless/pktradio/pktradio_loopback.c +++ b/wireless/pktradio/pktradio_loopback.c @@ -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 diff --git a/wireless/pktradio/pktradio_metadata.c b/wireless/pktradio/pktradio_metadata.c index d6bb4e7039..2bc94fee9d 100644 --- a/wireless/pktradio/pktradio_metadata.c +++ b/wireless/pktradio/pktradio_metadata.c @@ -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; }