From 9e760dcf6aed3ab2d1053e22d1116fcac8951e41 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Wed, 26 Apr 2017 11:30:54 -0400 Subject: [PATCH] wireless/ieee802154: Lots of little fixes and changes to get everything to build --- configs/clicker2-stm32/src/stm32_mrf24j40.c | 4 - drivers/wireless/ieee802154/mrf24j40.c | 60 +- .../wireless/ieee802154/ieee802154_mac.h | 51 +- .../wireless/ieee802154/ieee802154_radio.h | 37 +- wireless/ieee802154/Kconfig | 35 +- wireless/ieee802154/mac802154.c | 2548 +++++++++-------- wireless/ieee802154/mac802154.h | 34 +- wireless/ieee802154/mac802154_device.c | 24 +- wireless/ieee802154/radio802154_device.c | 6 +- 9 files changed, 1418 insertions(+), 1381 deletions(-) diff --git a/configs/clicker2-stm32/src/stm32_mrf24j40.c b/configs/clicker2-stm32/src/stm32_mrf24j40.c index e1b664f28b..18751e27dc 100644 --- a/configs/clicker2-stm32/src/stm32_mrf24j40.c +++ b/configs/clicker2-stm32/src/stm32_mrf24j40.c @@ -67,10 +67,6 @@ # error Wireless support requires CONFIG_DRIVERS_WIRELESS #endif -#ifndef CONFIG_IEEE802154_DEV -# error IEEE802.15.4 radio character device required (CONFIG_IEEE802154_DEV) -#endif - #if !defined(CONFIG_CLICKER2_STM32_MB1_BEE) && \ !defined(CONFIG_CLICKER2_STM32_MB2_BEE) # error Only the Mikroe BEE board is supported diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index 1e07d1126b..b819ed7d99 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -56,6 +56,8 @@ #include #include +#include + #include #include #include @@ -221,8 +223,7 @@ static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_radiocb_s *radiocb); static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *radio, int cmd, unsigned long arg); -static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, - bool state, FAR struct ieee802154_packet_s *packet); +static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio); static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, FAR uint8_t *buf, uint16_t buf_len); static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio); @@ -324,7 +325,7 @@ static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio) static void mrf24j40_dopoll_csma(FAR void *arg) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; - int ret = 0; + int len = 0; /* Need to get exlusive access to the device so that we can use the copy * buffer. @@ -338,9 +339,9 @@ static void mrf24j40_dopoll_csma(FAR void *arg) { /* need to somehow allow for a handle to be passed */ - ret = dev->radiocb->poll_csma(dev->radiocb, &dev->csma_desc.pub, + len = dev->radiocb->poll_csma(dev->radiocb, &dev->csma_desc.pub, &dev->tx_buf[0]); - if (ret > 0) + if (len > 0) { /* Now the txdesc is in use */ @@ -348,8 +349,7 @@ static void mrf24j40_dopoll_csma(FAR void *arg) /* Setup the transaction on the device in the CSMA FIFO */ - mrf24j40_csma_setup(dev, &dev->tx_buf[0], - dev->csma_desc.pub.psdu_length); + mrf24j40_csma_setup(dev, &dev->tx_buf[0], len); } } @@ -419,7 +419,7 @@ static void mrf24j40_dopoll_gts(FAR void *arg) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; int gts = 0; - int ret = 0; + int len = 0; /* Need to get exclusive access to the device so that we can use the copy * buffer. @@ -431,9 +431,9 @@ static void mrf24j40_dopoll_gts(FAR void *arg) { if (!dev->gts_desc[gts].busy) { - ret = dev->radiocb->poll_gts(dev->radiocb, &dev->gts_desc[gts].pub, + len = dev->radiocb->poll_gts(dev->radiocb, &dev->gts_desc[gts].pub, &dev->tx_buf[0]); - if (ret > 0) + if (len > 0) { /* Now the txdesc is in use */ @@ -441,8 +441,7 @@ static void mrf24j40_dopoll_gts(FAR void *arg) /* Setup the transaction on the device in the open GTS FIFO */ - mrf24j40_gts_setup(dev, gts, &dev->tx_buf[0], - dev->gts_desc[gts].pub.psdu_length); + mrf24j40_gts_setup(dev, gts, &dev->tx_buf[0], len); } } } @@ -1583,27 +1582,18 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, * ****************************************************************************/ -static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool state, - FAR struct ieee802154_packet_s *packet) +static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; uint8_t reg; - if (state) - { - mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - radio->rxbuf = packet; + mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - /* Enable rx int */ + /* Enable rx int */ - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg &= ~MRF24J40_INTCON_RXIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - } - else - { - radio->rxbuf = NULL; - } + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg &= ~MRF24J40_INTCON_RXIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); return OK; } @@ -1619,7 +1609,7 @@ static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool state, static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) { FAR struct iob_s *iob; - struct ieee802154_txdesc_s rxdesc; + struct ieee802154_rxdesc_s rxdesc; uint32_t addr; uint32_t index; uint8_t reg; @@ -1636,7 +1626,6 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV); - /* Allocate an IOB to put the packet in */ iob = iob_alloc(true); @@ -1675,7 +1664,8 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) /* Callback the receiver in the next highest layer */ - dev->radiocb->rx_frame(dev->radiocb, &rxdesc, iob); + dev->radiocb->rxframe(dev->radiocb, + (FAR const struct ieee802154_rxdesc_s *)&rxdesc, iob); /* Enable reception of next packet by flushing the fifo. * This is an MRF24J40 errata (no. 1). @@ -1831,16 +1821,6 @@ FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, dev->radio.ops = &mrf24j40_devops; - /* Initialize semaphores */ - - sem_init(&dev->radio.rxsem, 0, 0); - - /* These semaphores are all used for signaling and, hence, should - * not have priority inheritance enabled. - */ - - sem_setprotocol(&dev->radio.rxsem, SEM_PRIO_NONE); - dev->lower = lower; dev->spi = spi; diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 95ccf10ecd..e1aca5de75 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -55,6 +55,8 @@ # include #endif +#include + #include /**************************************************************************** @@ -553,45 +555,7 @@ struct ieee802154_data_req_s struct ieee802154_data_conf_s { - uint8_t msdu_handle; /* Handle assoc. with MSDU */ - - /* The time, in symbols, at which the data were transmitted */ - - uint32_t timestamp; - - enum ieee802154_status_e status; /* The status of the MSDU transmission */ - -#ifdef CONFIG_IEEE802154_RANGING - bool rng_rcvd; /* Ranging indicated by MSDU */ - - /* A count of the time units corresponding to an RMARKER at the antenna at - * the beginning of the ranging exchange - */ - - uint32_t rng_counter_start; - - /* A count of the time units corresponding to an RMARKER at the antenna at - * end of the ranging exchange - */ - - uint32_t rng_counter_stop; - - /* A count of the time units in a message exchange over which the tracking - * offset was measured - */ - - uint34_t rng_tracking_interval; - - /* A count of the time units slipped or advanced by the radio tracking - * system over the course of the entire tracking interval - */ - - uint32_t rng_offset; - - /* The Figure of Merit (FoM) characterizing the ranging measurement */ - - uint8_t rng_fom; -#endif + IEEE802154_TXDESC_FIELDS }; /***************************************************************************** @@ -1111,7 +1075,6 @@ struct ieee802154_rxenable_conf_s struct ieee802154_scan_req_s { - enum ieee802154_scantype_e type; uint8_t duration; uint8_t ch_page; @@ -1406,13 +1369,13 @@ enum ieee802154_macnotify_e struct ieee802154_maccb_s { - CODE void (*mlme_notify) (FAR struct ieee802154_maccb_s *maccb, + CODE void (*mlme_notify) (FAR const struct ieee802154_maccb_s *maccb, enum ieee802154_macnotify_e notif, - FAR union ieee802154_mlme_notify_u *arg); + FAR const union ieee802154_mlme_notify_u *arg); - CODE void (*mcps_notify) (FAR struct ieee802154_maccb_s *maccb, + CODE void (*mcps_notify) (FAR const struct ieee802154_maccb_s *maccb, enum ieee802154_macnotify_e notif, - FAR union ieee802154_mcps_notify_u *arg); + FAR const union ieee802154_mcps_notify_u *arg); }; #ifdef __cplusplus diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index 58748b267a..54e08969d9 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -158,12 +158,30 @@ struct ieee802154_netradio_s /* IEEE802.15.4 Radio Interface Operations **********************************/ +/* This is a work-around to allow the MAC upper layer have a struct with + * identical members but with a different name. */ + +#ifdef CONFIG_IEEE802154_RANGING +#define IEEE802154_TXDESC_FIELDS \ + uint8_t handle; \ + uint32_t timestamp; \ + uint8_t status; +#else +#define IEEE802154_TXDESC_FIELDS \ + uint8_t handle; \ + uint32_t timestamp; \ + uint8_t status; + bool rng_rcvd; \ + uint32_t rng_counter_start; \ + uint32_t rng_counter_stop; \ + uint32_t rng_tracking_interval; \ + uint32_t rng_offset;\ + uint8_t rng_fom; +#endif + struct ieee802154_txdesc_s { - uint8_t psdu_handle; /* The psdu handle identifying the transaction */ - uint16_t psdu_length; /* The length of the PSDU */ - uint8_t status; /* The status of the transaction. This is set by the - * radio layer prior to calling txdone_csma */ + IEEE802154_TXDESC_FIELDS /* TODO: Add slotting information for GTS transactions */ }; @@ -176,13 +194,13 @@ struct ieee802154_rxdesc_s struct ieee802154_radiocb_s { - CODE int (*poll_csma) (FAR struct ieee802154_radiocb_s *radiocb, + CODE int (*poll_csma) (FAR const struct ieee802154_radiocb_s *radiocb, FAR struct ieee802154_txdesc_s *tx_desc, FAR uint8_t *buf); - CODE int (*poll_gts) (FAR struct ieee802154_radiocb_s *radiocb, + CODE int (*poll_gts) (FAR const struct ieee802154_radiocb_s *radiocb, FAR struct ieee802154_txdesc_s *tx_desc, FAR uint8_t *buf); - CODE int (*txdone) (FAR struct ieee802154_radiocb_s *radiocb, + CODE void (*txdone) (FAR const struct ieee802154_radiocb_s *radiocb, FAR const struct ieee802154_txdesc_s *tx_desc); - CODE int (*rx_frame) (FAR struct ieee802154_radiocb_s *radiocb, + CODE void (*rxframe) (FAR const struct ieee802154_radiocb_s *radiocb, FAR const struct ieee8021254_rxdesc_s *rx_desc, FAR struct iob_s *frame); }; @@ -195,8 +213,7 @@ struct ieee802154_radioops_s FAR struct ieee802154_radiocb_s *radiocb); CODE int (*ioctl)(FAR struct ieee802154_radio_s *radio, int cmd, unsigned long arg); - CODE int (*rxenable)(FAR struct ieee802154_radio_s *radio, bool state, - FAR struct ieee802154_packet_s *packet); + CODE int (*rxenable)(FAR struct ieee802154_radio_s *radio); CODE int (*txnotify_csma)(FAR struct ieee802154_radio_s *radio); CODE int (*txnotify_gts)(FAR struct ieee802154_radio_s *radio); }; diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index 64b9e66e91..c1f7f828fa 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -6,13 +6,14 @@ config WIRELESS_IEEE802154 bool "IEEE 802.15.4 Wireless Support" default n + select DRIVERS_IOB ---help--- Enables support for the IEEE 802.14.5 Wireless library. if WIRELESS_IEEE802154 -config IEEE802154_MAC - bool "Generic Media Access Control layer for 802.15.4 radios" +menuconfig IEEE802154_MAC + bool "Generic Media Access Control (MAC) layer for 802.15.4 radios" default n depends on WIRELESS_IEEE802154 ---help--- @@ -21,6 +22,8 @@ config IEEE802154_MAC such as 6lowpan. It is not required to use 802.15.4 radios, but is strongly suggested to ensure exchange of valid frames. +if IEEE802154_MAC + config IEEE802154_MAC_DEV bool "Character driver for IEEE 802.15.4 MAC layer" default n @@ -29,6 +32,34 @@ config IEEE802154_MAC_DEV Enable the device driver to expose the IEEE 802.15.4 MAC layer access to user space as IOCTLs +choice + prompt "IEEE 802.15.4 work queue" + default MAC802154_LPWORK if SCHED_LPWORK + default MAC802154_HPWORK if !SCHED_LPWORK && SCHED_HPWORK + depends on SCHED_WORKQUEUE + ---help--- + Work queue support is required to use the IEEE 802.15.4 MAC layer. + If the low priority work queue is available, then it should be used by + the driver. + +config MAC802154_HPWORK + bool "High priority" + depends on SCHED_HPWORK + +config MAC802154_LPWORK + bool "Low priority" + depends on SCHED_LPWORK + +endchoice # Work queue + +config IEEE802154_NTXDESC + int "Number or TX descriptors" + default 3 + ---help--- + Configured number of Tx descriptors. Default: 3 + +endif # IEEE802154_MAC + config IEEE802154_DEV bool "Debug character driver for ieee802.15.4 radio interfaces" default n diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index ca877d5442..54e5782b41 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -1,1252 +1,1296 @@ -/**************************************************************************** - * wireless/ieee802154/mac802154.c - * - * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. - * Author: Sebastien Lorquet - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "mac802154.h" - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct mac802154_trans_s -{ - /* Supports a singly linked list */ - - FAR struct mac802154_trans_s *flink; - - uint8_t msdu_handle; - - FAR uint8_t *mhr_buf; - uint8_t mhr_len; - - FAR uint8_t *d_buf; - uint8_t d_len; - - sem_t sem; -}; - -struct mac802154_unsec_mhr_s -{ - uint8_t length; - union - { - uint16_t frame_control; - uint8_t data[IEEE802154_MAX_UNSEC_MHR_OVERHEAD]; - } u; -}; - -struct mac802154_radiocb_s -{ - struct ieee802154_radiocb_s cb; - FAR struct ieee802154_privmac_s *priv; -}; - -/* The privmac structure holds the internal state of the MAC and is the - * underlying represention of the opaque MACHANDLE. It contains storage for - * the IEEE802.15.4 MIB attributes. - */ - -struct ieee802154_privmac_s -{ - FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */ - FAR const struct ieee802154_maccb_s *cb; /* Contained MAC callbacks */ - FAR struct mac802154_radiocb_s radiocb; /* Interface to bind to radio */ - - sem_t exclsem; /* Support exclusive access */ - - struct work_s tx_work; - struct work_s rx_work; - - /* Support a singly linked list of transactions that will be sent using the - * CSMA algorithm. On a non-beacon enabled PAN, these transactions will be - * sent whenever. On a beacon-enabled PAN, these transactions will be sent - * during the CAP of the Coordinator's superframe. - */ - - FAR struct mac802154_trans_s *csma_head; - FAR struct mac802154_trans_s *csma_tail; - - /* Support a singly linked list of transactions that will be sent indirectly. - * This list should only be used by a MAC acting as a coordinator. These - * transactions will stay here until the data is extracted by the destination - * device sending a Data Request MAC command or if too much time passes. This - * list should also be used to populate the address list of the outgoing - * beacon frame. - */ - - FAR struct mac802154_trans_s *indirect_head; - FAR struct mac802154_trans_s *indirect_tail; - - FAR struct ieee802154_txdesc_s *txhead; /* Next TX descriptor to handle */ - FAR struct ieee802154_txdesc_s *txtail; /* Location to push TX descriptor */ - struct ieee802154_txdesc_s txtable[CONFIG_IEEE802154_NTXDESC]; - - /* MAC PIB attributes, grouped to save memory */ - - /* Holds all address information (Extended, Short, and PAN ID) for the MAC. */ - - struct ieee802154_addr_s addr; - - /* Holds all address information (Extended, Short) for Coordinator */ - - struct ieee802154_addr_s coord_addr; - - /* The maximum number of symbols to wait for an acknowledgement frame to - * arrive following a transmitted data frame. [1] pg. 126 - * - * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't - * sure at the time what the range of reasonable values was. - */ - - uint32_t ack_wait_dur; - - /* The maximum time to wait either for a frame intended as a response to a - * data request frame or for a broadcast frame following a beacon with the - * Frame Pending field set to one. [1] pg. 127 - * - * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't - * sure at the time what the range of reasonable values was. - */ - - uint32_t max_frame_wait_time; - - /* The maximum time (in unit periods) that a transaction is stored by a - * coordinator and indicated in its beacon. - */ - - uint16_t trans_persist_time; - - /* Contents of beacon payload */ - - uint8_t beacon_payload[IEEE802154_MAX_BEACON_PAYLOAD_LENGTH]; - uint8_t beacon_payload_len; /* Length of beacon payload */ - - uint8_t batt_life_ext_periods; /* # of backoff periods during which rx is - * enabled after the IFS following beacon */ - - uint8_t bsn; /* Seq. num added to tx beacon frame */ - uint8_t dsn; /* Seq. num added to tx data or MAC frame */ - uint8_t max_retries; /* Max # of retries alloed after tx failure */ - - /* The maximum time, in multiples of aBaseSuperframeDuration, a device shall - * wait for a response command frame to be available following a request - * command frame. [1] 128. - */ - - uint8_t resp_wait_time; - - /* The total transmit duration (including PHY header and FCS) specified in - * symbols. [1] pg. 129. - */ - - uint32_t tx_total_dur; - - /* Start of 32-bit bitfield */ - - uint32_t is_assoc : 1; /* Are we associated to the PAN */ - uint32_t assoc_permit : 1; /* Are we allowing assoc. as a coord. */ - uint32_t auto_req : 1; /* Automatically send data req. if addr - * addr is in the beacon frame */ - - uint32_t batt_life_ext : 1; /* Is BLE enabled */ - uint32_t gts_permit : 1; /* Is PAN Coord. accepting GTS reqs. */ - uint32_t promiscuous_mode : 1; /* Is promiscuous mode on? */ - uint32_t ranging_supported : 1; /* Does MAC sublayer support ranging */ - uint32_t rx_when_idle : 1; /* Recvr. on during idle periods */ - uint32_t sec_enabled : 1; /* Does MAC sublayer have security en. */ - - uint32_t max_csma_backoffs : 3; /* Max num backoffs for CSMA algorithm - * before declaring ch access failure */ - - uint32_t beacon_order : 4; /* Freq. that beacon is transmitted */ - - uint32_t superframe_order : 4; /* Length of active portion of outgoing - * superframe, including the beacon */ - - /* The offset, measured is symbols, between the symbol boundary at which the - * MLME captures the timestamp of each transmitted and received frame, and - * the onset of the first symbol past the SFD, namely the first symbol of - * the frames [1] pg. 129. - */ - - uint32_t sync_symb_offset : 12; - - /* End of 32-bit bitfield */ - - /* Start of 32-bit bitfield */ - - uint32_t beacon_tx_time : 24; /* Time of last beacon transmit */ - uint32_t min_be : 4; /* Min value of backoff exponent (BE) */ - uint32_t max_be : 4; /* Max value of backoff exponent (BE) */ - - /* End of 32-bit bitfield */ - - /* Start of 32-bit bitfield */ - - uint32_t tx_ctrl_active_dur : 17; /* Duration for which tx is permitted to - * be active */ - uint32_t tx_ctrl_pause_dur : 1; /* Duration after tx before another tx is - * permitted. 0=2000, 1= 10000 */ - uint32_t timestamp_support : 1; /* Does MAC layer supports timestamping */ - uint32_t is_coord : 1; /* Is this device acting as coordinator */ - /* 12-bits remaining */ - - /* End of 32-bit bitfield. */ - - /* TODO: Add Security-related MAC PIB attributes */ -}; - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static inline int mac802154_takesem(sem_t *sem); -#define mac802154_givesem(s) sem_post(s); - -/* Internal Functions */ - -static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv); -static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv); - -/* IEEE 802.15.4 PHY Interface OPs */ - -static int mac802154_poll_csma(FAR struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc, - FAR uint8_t *buf); - -static int mac802154_poll_gts(FAR struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc, - FAR uint8_t *buf); - -static int mac802154_txdone(FAR struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc); - -/**************************************************************************** - * Private Data - ****************************************************************************/ - - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: mac802154_semtake - * - * Description: - * Acquire the semaphore used for access serialization. - * - ****************************************************************************/ - -static inline int mac802154_takesem(sem_t *sem) -{ - /* Take a count from the semaphore, possibly waiting */ - - if (sem_wait(sem) < 0) - { - /* EINTR is the only error that we expect */ - - int errcode = get_errno(); - DEBUGASSERT(errcode == EINTR); - return -errcode; - } - - return OK; -} - -/**************************************************************************** - * Name: mac802154_defaultmib - * - * Description: - * Set the MIB to its default values. - * - ****************************************************************************/ - -static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv) -{ - /* TODO: Set all MAC fields to default values */ - - return OK; -} - -/**************************************************************************** - * Name: mac802154_applymib - * - * Description: - * Some parts of the MIB must be sent to the radio device. This routine - * calls the radio device routines to store the related parameters in the - * radio driver. It must be called each time a MIB parameter is changed. - * - ****************************************************************************/ - -static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv) -{ - return OK; -} - -/**************************************************************************** - * Name: mac802154_poll_csma - * - * Description: - * Called from the radio driver through the callback struct. This function is - * called when the radio has room for another CSMA transaction. If the MAC - * layer has a CSMA transaction, it copies it into the supplied buffer and - * returns the length. A descriptor is also populated with the transaction. - * - ****************************************************************************/ - -static int mac802154_poll_csma(FAR struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc, - FAR uint8_t *buf) -{ - FAR struct mac802154_radiocb_s *cb = - (FAR struct mac802154_radiocb_s *)radiocb; - FAR struct ieee802154_privmac_s *priv; - FAR struct mac802154_trans_s *trans; - - DEBUGASSERT(cb != NULL && cb->priv != NULL); - priv = cb->priv; - - /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. - */ - - while (mac802154_takesem(&priv->exclsem) != 0); - - /* Check to see if there are any CSMA transactions waiting */ - - if (priv->csma_head) - { - /* Pop a CSMA transaction off the list */ - - trans = priv->csma_head; - priv->csma_head = priv->csma_head->flink; - - mac802154_givesem(&priv->exclsem); - - /* Setup the transmit descriptor */ - - tx_desc->psdu_handle = trans->msdu_handle; - tx_desc->psdu_length = trans->mhr_len + trans->d_len; - - /* Copy the frame into the buffer */ - - memcpy(&buf[0], trans->mhr_buf, trans->mhr_len); - memcpy(&buf[trans->mhr_len], trans->d_buf, trans->d_len); - - /* Now that we've passed off the data, notify the waiting thread. - * NOTE: The transaction was allocated on the waiting thread's stack so - * it will be automatically deallocated when that thread awakens and - * returns. - */ - - sem_post(&trans->sem); - return tx_desc->psdu_length; - } - - mac802154_givesem(&priv->exclsem); - return 0; -} - -/**************************************************************************** - * Name: mac802154_poll_gts - * - * Description: - * Called from the radio driver through the callback struct. This function is - * called when the radio has room for another GTS transaction. If the MAC - * layer has a GTS transaction, it copies it into the supplied buffer and - * returns the length. A descriptor is also populated with the transaction. - * - ****************************************************************************/ - -static int mac802154_poll_gts(FAR struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc, - FAR uint8_t *buf) -{ - FAR struct mac802154_radiocb_s *cb = - (FAR struct mac802154_radiocb_s *)radiocb; - FAR struct ieee802154_privmac_s *priv; - FAR struct mac802154_trans_s *trans; - int ret = 0; - - DEBUGASSERT(cb != NULL && cb->priv != NULL); - priv = cb->priv; - - /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. - */ - - while (mac802154_takesem(&priv->exclsem) != 0); - -#warning Missing logic. - - mac802154_givesem(&priv->exclsem); - - return 0; -} - -/**************************************************************************** - * Name: mac802154_txdone - * - * Description: - * Called from the radio driver through the callback struct. This function is - * called when the radio has completed a transaction. The txdesc passed gives - * provides information about the completed transaction including the original - * handle provided when the transaction was created and the status of the - * transaction. This function copies the descriptor and schedules work to - * handle the transaction without blocking the radio. - * - ****************************************************************************/ - -static int mac802154_txdone(FAR struct ieee802154_radiocb_s *radiocb, - FAR const struct ieee802154_txdesc_s *tx_desc) -{ - FAR struct mac802154_radiocb_s *cb = - (FAR struct mac802154_radiocb_s *)radiocb; - FAR struct ieee802154_privmac_s *priv; - FAR struct ieee802154_txdesc_s *desc; - int ret = 0; - - DEBUGASSERT(cb != NULL && cb->priv != NULL); - priv = cb->priv; - - /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. - */ - - while (mac802154_takesem(&priv->exclsem) != 0); - - /* Allocate a tx_desc */ - - desc = kmm_zalloc(sizeof(struct ieee802154_txdesc_s)); - if (desc == NULL) - { - mac802154_givesem(&priv->exclsem); - - return -ENOMEM; - } - - /* Copy the txdesc over and link it into our list */ - - memcpy(desc, tx_desc, sizeof(ieee802154_txdesc_s)); - - /* Link the descriptor */ - -#warning Missing Logic! - - mac802154_givesem(&priv->exclsem); - - /* Schedule work with the work queue to process the completion further */ - - if (work_available(&priv->tx_work)) - { - work_queue(MAC802154_WORK, &priv->tx_work, mac802154_txdone_worker, - (FAR void *)dev, 0); - } -} - -/**************************************************************************** - * Name: mac802154_txdone_worker - * - * Description: - * Worker function scheduled from mac802154_txdone. This function pops any - * TX descriptors off of the list and calls the next highest layers callback - * to inform the layer of the completed transaction and the status of it. - * - ****************************************************************************/ - -static void mac802154_txdone_worker(FAR void *arg) -{ - FAR struct ieee802154_privmanc_s *priv = - (FAR struct ieee802154_privmanc_s *)arg; -} - -/**************************************************************************** - * Name: mac802154_rxframe - * - * Description: - * Called from the radio driver through the callback struct. This function is - * called when the radio has received a frame. The frame is passed in an iob, - * so that we can free it when we are done processing. A pointer to the RX - * descriptor is passed along with the iob, but it must be copied here as it - * is allocated directly on the caller's stack. We simply link the frame, - * copy the RX descriptor, and schedule a worker to process the frame later so - * that we do not hold up the radio. - * - ****************************************************************************/ - -static void mac802154_rxframe(FAR struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_rxdesc_s *rx_desc, - FAR struct iob_s *frame) -{ - FAR struct mac802154_radiocb_s *cb = - (FAR struct mac802154_radiocb_s *)radiocb; - FAR struct ieee802154_privmac_s *priv; - FAR struct ieee802154_txdesc_s *desc; - int ret = 0; - - DEBUGASSERT(cb != NULL && cb->priv != NULL); - priv = cb->priv; - - /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. - */ - - while (mac802154_takesem(&priv->exclsem) != 0); - - /* TODO: Copy the frame descriptor to some type of list */ - - /* Push the iob onto the tail of the frame list for processing */ - - priv->rxframes_tail->io_flink = iob; - priv->rxframes_tail = iob; - - mac802154_givesem(&priv->exclsem); - - /* Schedule work with the work queue to process the completion further */ - - if (work_available(&priv->rx_work)) - { - work_queue(MAC802154_WORK, &priv->rx_work, mac802154_rxframe_worker, - (FAR void *)priv, 0); - } -} - -/**************************************************************************** - * Name: mac802154_rxframe_worker - * - * Description: - * Worker function scheduled from mac802154_rxframe. This function processes - * any frames in the list. Frames intended to be consumed by the MAC layer - * will not produce any callbacks to the next highest layer. Frames intended - * for the application layer will be forwarded to them. - * - ****************************************************************************/ - -static void mac802154_rxframe_worker(FAR void *arg) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)arg; - - /* The radio layer is responsible for handling all ACKs and retries. If for - * some reason an ACK gets here, just throw it out. - */ -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: mac802154_create - * - * Description: - * Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. - * - * The returned MAC structure should be passed to either the next highest - * layer in the network stack, or registered with a mac802154dev character - * or network drivers. In any of these scenarios, the next highest layer - * should register a set of callbacks with the MAC layer by setting the - * mac->cbs member. - * - * NOTE: This API does not create any device accessible to userspace. If - * you want to call these APIs from userspace, you have to wrap your mac - * in a character device via mac802154_device.c. - * - * Input Parameters: - * radiodev - an instance of an IEEE 802.15.4 radio - * - * Returned Value: - * An opaque reference to the MAC state data. - * - ****************************************************************************/ - -MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) -{ - FAR struct ieee802154_privmac_s *mac; - FAR struct ieee802154_radiocb_s *radiocb; - - /* Allocate object */ - - mac = (FAR struct ieee802154_privmac_s *) - kmm_zalloc(sizeof(struct ieee802154_privmac_s)); - - if (mac == NULL) - { - return NULL; - } - - /* Initialize fields */ - - mac->radio = radiodev; - - mac802154_defaultmib(mac); - mac802154_applymib(mac); - - /* Initialize the Radio callbacks */ - - mac->radiocb.priv = mac; - - radiocb = &mac->radiocb.cb; - radiocb->poll_csma = mac802154_poll_csma; - radiocb->poll_gts = mac802154_poll_gts; - radiocb->txdone = mac802154_txdone; - - /* Bind our callback structure */ - - radiodev->ops->bind(radiodev, &mac->radiocb.cb); - - return (MACHANDLE)mac; -} - -/**************************************************************************** - * Name: mac802154_bind - * - * Description: - * Bind the MAC callback table to the MAC state. - * - * Parameters: - * mac - Reference to the MAC driver state structure - * cb - MAC callback operations - * - * Returned Value: - * OK on success; Negated errno on failure. - * - ****************************************************************************/ - -int mac802154_bind(MACHANDLE mac, FAR const struct ieee802154_maccb_s *cb) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - - priv->cb = cb; - return OK; -} - -/**************************************************************************** - * Name: mac802154_ioctl - * - * Description: - * Handle MAC and radio IOCTL commands directed to the MAC. - * - * Parameters: - * mac - Reference to the MAC driver state structure - * cmd - The IOCTL command - * arg - The argument for the IOCTL command - * - * Returned Value: - * OK on success; Negated errno on failure. - * - ****************************************************************************/ - -int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - int ret = -EINVAL; - - DEBUGASSERT(priv != NULL); - - /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */ - - if (_MAC802154IOCVALID(cmd)) - { - /* Handle the MAC IOCTL command */ -#warning Missing logic - } - - /* No, other IOCTLs must be aimed at the IEEE802.15.4 radio layer */ - - else - { - DEBUGASSERT(priv->radio != NULL && - priv->radio->ops != NULL && - priv->radio->ops->ioctl != NULL); - - ret = priv->radio->ops->ioctl(priv->radio, cmd, arg); - } - - return ret; -} - -/**************************************************************************** - * MAC Interface Operations - ****************************************************************************/ - -/**************************************************************************** - * Name: mac802154_req_data - * - * Description: - * The MCPS-DATA.request primitive requests the transfer of a data SPDU - * (i.e., MSDU) from a local SSCS entity to a single peer SSCS entity. - * Confirmation is returned via the - * struct ieee802154_maccb_s->conf_data callback. - * - ****************************************************************************/ - -int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - FAR struct mac802154_trans_s trans; - struct mac802154_unsec_mhr_s mhr; - int ret; - - /* Start off assuming there is only the frame_control field in the MHR */ - - mhr.length = 2; - - /* Do a preliminary check to make sure the MSDU isn't too long for even - * the best case. - */ - - if (req->msdu_length > IEEE802154_MAX_MAC_PAYLOAD_SIZE) - { - return -EINVAL; - } - - /* Ensure we start with a clear frame control field */ - - mhr.u.frame_control = 0; - - /* Set the frame type to Data */ - - mhr.u.frame_control |= IEEE802154_FRAME_DATA << - IEEE802154_FRAMECTRL_SHIFT_FTYPE; - - /* If the msduLength is greater than aMaxMACSafePayloadSize, the MAC - * sublayer will set the Frame Version to one. [1] pg. 118. - */ - - if (req->msdu_length > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) - { - mhr.u.frame_control |= IEEE802154_FRAMECTRL_VERSION; - } - - /* If the TXOptions parameter specifies that an acknowledged transmission - * is required, the AR field will be set appropriately, as described in - * 5.1.6.4 [1] pg. 118. - */ - - mhr.u.frame_control |= (req->msdu_flags.ack_tx << - IEEE802154_FRAMECTRL_SHIFT_ACKREQ); - - /* If the destination address is present, copy the PAN ID and one of the - * addresses, depending on mode, into the MHR . - */ - - if (req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - memcpy(&mhr.u.data[mhr.length], &req->dest_addr.panid, 2); - mhr.length += 2; - - if (req->dest_addr.mode == IEEE802154_ADDRMODE_SHORT) - { - memcpy(&mhr.u.data[mhr.length], &req->dest_addr.saddr, 2); - mhr.length += 2; - } - else if (req->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) - { - memcpy(&mhr.u.data[mhr.length], &req->dest_addr.eaddr, 8); - mhr.length += 8; - } - } - - /* Set the destination addr mode inside the frame contorl field */ - - mhr.u.frame_control |= (req->dest_addr.mode << - IEEE802154_FRAMECTRL_SHIFT_DADDR); - - /* From this point on, we need exclusive access to the privmac struct */ - - ret = mac802154_takesem(&priv->exclsem); - if (ret < 0) - { - wlerr("ERROR: mac802154_takesem failed: %d\n", ret); - return ret; - } - - /* If both destination and source addressing information is present, the MAC - * sublayer shall compare the destination and source PAN identifiers. - * [1] pg. 41. - */ - - if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE && - req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - /* If the PAN identifiers are identical, the PAN ID Compression field - * shall be set to one, and the source PAN identifier shall be omitted - * from the transmitted frame. [1] pg. 41. - */ - - if (req->dest_addr.panid == priv->addr.panid) - { - mhr.u.frame_control |= IEEE802154_FRAMECTRL_PANIDCOMP; - } - } - - if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE) - { - /* If the destination address is not included, or if PAN ID Compression - * is off, we need to include the Source PAN ID. - */ - - if ((req->dest_addr.mode == IEEE802154_ADDRMODE_NONE) || - (mhr.u.frame_control & IEEE802154_FRAMECTRL_PANIDCOMP)) - { - memcpy(&mhr.u.data[mhr.length], &priv->addr.panid, 2); - mhr.length += 2; - } - - if (req->src_addr_mode == IEEE802154_ADDRMODE_SHORT) - { - memcpy(&mhr.u.data[mhr.length], &priv->addr.saddr, 2); - mhr.length += 2; - } - else if (req->src_addr_mode == IEEE802154_ADDRMODE_EXTENDED) - { - memcpy(&mhr.u.data[mhr.length], &priv->addr.eaddr, 8); - mhr.length += 8; - } - } - - /* Set the source addr mode inside the frame control field */ - - mhr.u.frame_control |= (req->src_addr_mode << - IEEE802154_FRAMECTRL_SHIFT_SADDR); - - /* Each time a data or a MAC command frame is generated, the MAC sublayer - * shall copy the value of macDSN into the Sequence Number field of the MHR - * of the outgoing frame and then increment it by one. [1] pg. 40. - */ - - mhr.u.data[mhr.length++] = priv->dsn++; - - /* Now that we know which fields are included in the header, we can make - * sure we actually have enough room in the PSDU. - */ - - if (mhr.length + req->msdu_length + IEEE802154_MFR_LENGTH > - IEEE802154_MAX_PHY_PACKET_SIZE) - { - return -E2BIG; - } - - trans.mhr_buf = &mhr.u.data[0]; - trans.mhr_len = mhr.length; - - trans.d_buf = &req->msdu[0]; - trans.d_len = req->msdu_length; - - trans.msdu_handle = req->msdu_handle; - - /* If the TxOptions parameter specifies that a GTS transmission is required, - * the MAC sublayer will determine whether it has a valid GTS as described - * 5.1.7.3. If a valid GTS could not be found, the MAC sublayer will discard - * the MSDU. If a valid GTS was found, the MAC sublayer will defer, if - * necessary, until the GTS. If the TxOptions parameter specifies that a GTS - * transmission is not required, the MAC sublayer will transmit the MSDU using - * either slotted CSMA-CA in the CAP for a beacon-enabled PAN or unslotted - * CSMA-CA for a nonbeacon-enabled PAN. Specifying a GTS transmission in the - * TxOptions parameter overrides an indirect transmission request. - * [1] pg. 118. - */ - - if (req->msdu_flags.gts_tx) - { - /* TODO: Support GTS transmission. This should just change where we link - * the transaction. Instead of going in the CSMA transaction list, it - * should be linked to the GTS' transaction list. We'll need to check if - * the GTS is valid, and then find the GTS, before linking. Note, we also - * don't have to try and kick-off any transmission here. - */ - - return -ENOTSUP; - } - else - { - /* If the TxOptions parameter specifies that an indirect transmission is - * required and this primitive is received by the MAC sublayer of a - * coordinator, the data frame is sent using indirect transmission, as - * described in 5.1.5 and 5.1.6.3. [1] - */ - - if (req->msdu_flags.indirect_tx) - { - /* If the TxOptions parameter specifies that an indirect transmission - * is required and if the device receiving this primitive is not a - * coordinator, the destination address is not present, or the - * TxOptions parameter also specifies a GTS transmission, the indirect - * transmission option will be ignored. [1] - */ - - if (priv->is_coord && req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - /* Link the transaction into the indirect_trans list */ - - priv->indirect_tail->flink = &trans; - priv->indirect_tail = &trans; - } - else - { - /* Override the setting since it wasn't valid */ - - req->msdu_flags.indirect_tx = 0; - } - } - - /* If this is a direct transmission not during a GTS */ - - if (!req->msdu_flags.indirect_tx) - { - /* Link the transaction into the CSMA transaction list */ - - priv->csma_tail->flink = &trans; - priv->csma_tail = &trans; - - /* We no longer need to have the MAC layer locked. */ - - mac802154_givesem(&priv->exclsem); - - /* Notify the radio driver that there is data available */ - - priv->radio->ops->txnotify_csma(priv->radio); - - sem_wait(&trans.sem); - } - } - - return OK; -} - - -/**************************************************************************** - * Name: mac802154_req_purge - * - * Description: - * The MCPS-PURGE.request primitive allows the next higher layer to purge - * an MSDU from the transaction queue. Confirmation is returned via - * the struct ieee802154_maccb_s->conf_purge callback. - * - ****************************************************************************/ - -int mac802154_req_purge(MACHANDLE mac, uint8_t handle) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_associate - * - * Description: - * The MLME-ASSOCIATE.request primitive allows a device to request an - * association with a coordinator. Confirmation is returned via the - * struct ieee802154_maccb_s->conf_associate callback. - * - ****************************************************************************/ - -int mac802154_req_associate(MACHANDLE mac, - FAR struct ieee802154_assoc_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - - /* Set the channel of the PHY layer */ - - /* Set the channel page of the PHY layer */ - - /* Set the macPANId */ - - /* Set either the macCoordExtendedAddress and macCoordShortAddress - * depending on the CoordAddrMode in the primitive. - */ - - if (req->coord_addr.mode == IEEE802154_ADDRMODE_EXTENDED) - { - - } - else if (req->coord_addr.mode == IEEE802154_ADDRMODE_EXTENDED) - { - - } - else - { - return -EINVAL; - } - - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_disassociate - * - * Description: - * The MLME-DISASSOCIATE.request primitive is used by an associated device to - * notify the coordinator of its intent to leave the PAN. It is also used by - * the coordinator to instruct an associated device to leave the PAN. - * Confirmation is returned via the - * struct ieee802154_maccb_s->conf_disassociate callback. - * - ****************************************************************************/ - -int mac802154_req_disassociate(MACHANDLE mac, - FAR struct ieee802154_disassoc_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_get - * - * Description: - * The MLME-GET.request primitive requests information about a given PIB - * attribute. Actual data is returned via the - * struct ieee802154_maccb_s->conf_get callback. - * - ****************************************************************************/ - -int mac802154_req_get(MACHANDLE mac, enum ieee802154_pib_attr_e attr) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_gts - * - * Description: - * The MLME-GTS.request primitive allows a device to send a request to the PAN - * coordinator to allocate a new GTS or to deallocate an existing GTS. - * Confirmation is returned via the - * struct ieee802154_maccb_s->conf_gts callback. - * - ****************************************************************************/ - -int mac802154_req_gts(MACHANDLE mac, FAR uint8_t *characteristics) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_reset - * - * Description: - * The MLME-RESET.request primitive allows the next higher layer to request - * that the MLME performs a reset operation. Confirmation is returned via - * the struct ieee802154_maccb_s->conf_reset callback. - * - ****************************************************************************/ - -int mac802154_req_reset(MACHANDLE mac, bool setdefaults) -{ - FAR struct ieee802154_privmac_s * priv = - (FAR struct ieee802154_privmac_s *) mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_rxenable - * - * Description: - * The MLME-RX-ENABLE.request primitive allows the next higher layer to - * request that the receiver is enable for a finite period of time. - * Confirmation is returned via the - * struct ieee802154_maccb_s->conf_rxenable callback. - * - ****************************************************************************/ - -int mac802154_req_rxenable(MACHANDLE mac, bool deferrable, int ontime, - int duration) -{ - FAR struct ieee802154_privmac_s * priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_scan - * - * Description: - * The MLME-SCAN.request primitive is used to initiate a channel scan over a - * given list of channels. A device can use a channel scan to measure the - * energy on the channel, search for the coordinator with which it associated, - * or search for all coordinators transmitting beacon frames within the POS of - * the scanning device. Scan results are returned - * via MULTIPLE calls to the struct ieee802154_maccb_s->conf_scan callback. - * This is a difference with the official 802.15.4 specification, implemented - * here to save memory. - * - ****************************************************************************/ - -int mac802154_req_scan(MACHANDLE mac, uint8_t type, uint32_t channels, - int duration) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_set - * - * Description: - * The MLME-SET.request primitive attempts to write the given value to the - * indicated MAC PIB attribute. Confirmation is returned via the - * struct ieee802154_maccb_s->conf_set callback. - * - ****************************************************************************/ - -int mac802154_req_set(MACHANDLE mac, int attribute, FAR uint8_t *value, - int valuelen) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_start - * - * Description: - * The MLME-START.request primitive makes a request for the device to start - * using a new superframe configuration. Confirmation is returned - * via the struct ieee802154_maccb_s->conf_start callback. - * - ****************************************************************************/ - -int mac802154_req_start(MACHANDLE mac, uint16_t panid, int channel, - uint8_t bo, uint8_t fo, bool coord, bool batext, - bool realign) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_sync - * - * Description: - * The MLME-SYNC.request primitive requests to synchronize with the - * coordinator by acquiring and, if specified, tracking its beacons. - * Confirmation is returned via the - * struct ieee802154_maccb_s->int_commstatus callback. TOCHECK. - * - ****************************************************************************/ - -int mac802154_req_sync(MACHANDLE mac, int channel, bool track) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_poll - * - * Description: - * The MLME-POLL.request primitive prompts the device to request data from - * the coordinator. Confirmation is returned via the - * struct ieee802154_maccb_s->conf_poll callback, followed by a - * struct ieee802154_maccb_s->ind_data callback. - * - ****************************************************************************/ - -int mac802154_req_poll(MACHANDLE mac, FAR uint8_t *coordaddr) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_rsp_associate - * - * Description: - * The MLME-ASSOCIATE.response primitive is used to initiate a response to - * an MLME-ASSOCIATE.indication primitive. - * - ****************************************************************************/ - -int mac802154_rsp_associate(MACHANDLE mac, uint8_t eadr, uint16_t saddr, - int status) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_rsp_orphan - * - * Description: - * The MLME-ORPHAN.response primitive allows the next higher layer of a - * coordinator to respond to the MLME-ORPHAN.indication primitive. - * - ****************************************************************************/ - -int mac802154_rsp_orphan(MACHANDLE mac, FAR uint8_t *orphanaddr, - uint16_t saddr, bool associated) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} +/**************************************************************************** + * wireless/ieee802154/mac802154.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "mac802154.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* If processing is not done at the interrupt level, then work queue support + * is required. + */ + +#if !defined(CONFIG_SCHED_WORKQUEUE) +# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE) +#else + + /* Use the low priority work queue if possible */ + +# if defined(CONFIG_MAC802154_HPWORK) +# define MAC802154_WORK HPWORK +# elif defined(CONFIG_MAC802154_LPWORK) +# define MAC802154_WORK LPWORK +# else +# error Neither CONFIG_MAC802154_HPWORK nor CONFIG_MAC802154_LPWORK defined +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mac802154_trans_s +{ + /* Supports a singly linked list */ + + FAR struct mac802154_trans_s *flink; + + uint8_t msdu_handle; + + FAR uint8_t *mhr_buf; + uint8_t mhr_len; + + FAR uint8_t *d_buf; + uint8_t d_len; + + sem_t sem; +}; + +struct mac802154_unsec_mhr_s +{ + uint8_t length; + union + { + uint16_t frame_control; + uint8_t data[IEEE802154_MAX_UNSEC_MHR_OVERHEAD]; + } u; +}; + +struct mac802154_radiocb_s +{ + struct ieee802154_radiocb_s cb; + FAR struct ieee802154_privmac_s *priv; +}; + +/* The privmac structure holds the internal state of the MAC and is the + * underlying represention of the opaque MACHANDLE. It contains storage for + * the IEEE802.15.4 MIB attributes. + */ + +struct ieee802154_privmac_s +{ + FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */ + FAR const struct ieee802154_maccb_s *cb; /* Contained MAC callbacks */ + FAR struct mac802154_radiocb_s radiocb; /* Interface to bind to radio */ + + sem_t exclsem; /* Support exclusive access */ + + struct work_s tx_work; + struct work_s rx_work; + + /* Support a singly linked list of transactions that will be sent using the + * CSMA algorithm. On a non-beacon enabled PAN, these transactions will be + * sent whenever. On a beacon-enabled PAN, these transactions will be sent + * during the CAP of the Coordinator's superframe. + */ + + FAR struct mac802154_trans_s *csma_head; + FAR struct mac802154_trans_s *csma_tail; + + /* Support a singly linked list of transactions that will be sent indirectly. + * This list should only be used by a MAC acting as a coordinator. These + * transactions will stay here until the data is extracted by the destination + * device sending a Data Request MAC command or if too much time passes. This + * list should also be used to populate the address list of the outgoing + * beacon frame. + */ + + FAR struct mac802154_trans_s *indirect_head; + FAR struct mac802154_trans_s *indirect_tail; + + uint8_t txdesc_count; + struct ieee802154_txdesc_s txdesc[CONFIG_IEEE802154_NTXDESC]; + + /* Support a singly linked list of frames received */ + FAR struct iob_s *rxframes_head; + FAR struct iob_s *rxframes_tail; + + /* MAC PIB attributes, grouped to save memory */ + + /* Holds all address information (Extended, Short, and PAN ID) for the MAC. */ + + struct ieee802154_addr_s addr; + + /* Holds all address information (Extended, Short) for Coordinator */ + + struct ieee802154_addr_s coord_addr; + + /* The maximum number of symbols to wait for an acknowledgement frame to + * arrive following a transmitted data frame. [1] pg. 126 + * + * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't + * sure at the time what the range of reasonable values was. + */ + + uint32_t ack_wait_dur; + + /* The maximum time to wait either for a frame intended as a response to a + * data request frame or for a broadcast frame following a beacon with the + * Frame Pending field set to one. [1] pg. 127 + * + * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't + * sure at the time what the range of reasonable values was. + */ + + uint32_t max_frame_wait_time; + + /* The maximum time (in unit periods) that a transaction is stored by a + * coordinator and indicated in its beacon. + */ + + uint16_t trans_persist_time; + + /* Contents of beacon payload */ + + uint8_t beacon_payload[IEEE802154_MAX_BEACON_PAYLOAD_LENGTH]; + uint8_t beacon_payload_len; /* Length of beacon payload */ + + uint8_t batt_life_ext_periods; /* # of backoff periods during which rx is + * enabled after the IFS following beacon */ + + uint8_t bsn; /* Seq. num added to tx beacon frame */ + uint8_t dsn; /* Seq. num added to tx data or MAC frame */ + uint8_t max_retries; /* Max # of retries alloed after tx failure */ + + /* The maximum time, in multiples of aBaseSuperframeDuration, a device shall + * wait for a response command frame to be available following a request + * command frame. [1] 128. + */ + + uint8_t resp_wait_time; + + /* The total transmit duration (including PHY header and FCS) specified in + * symbols. [1] pg. 129. + */ + + uint32_t tx_total_dur; + + /* Start of 32-bit bitfield */ + + uint32_t is_assoc : 1; /* Are we associated to the PAN */ + uint32_t assoc_permit : 1; /* Are we allowing assoc. as a coord. */ + uint32_t auto_req : 1; /* Automatically send data req. if addr + * addr is in the beacon frame */ + + uint32_t batt_life_ext : 1; /* Is BLE enabled */ + uint32_t gts_permit : 1; /* Is PAN Coord. accepting GTS reqs. */ + uint32_t promiscuous_mode : 1; /* Is promiscuous mode on? */ + uint32_t ranging_supported : 1; /* Does MAC sublayer support ranging */ + uint32_t rx_when_idle : 1; /* Recvr. on during idle periods */ + uint32_t sec_enabled : 1; /* Does MAC sublayer have security en. */ + + uint32_t max_csma_backoffs : 3; /* Max num backoffs for CSMA algorithm + * before declaring ch access failure */ + + uint32_t beacon_order : 4; /* Freq. that beacon is transmitted */ + + uint32_t superframe_order : 4; /* Length of active portion of outgoing + * superframe, including the beacon */ + + /* The offset, measured is symbols, between the symbol boundary at which the + * MLME captures the timestamp of each transmitted and received frame, and + * the onset of the first symbol past the SFD, namely the first symbol of + * the frames [1] pg. 129. + */ + + uint32_t sync_symb_offset : 12; + + /* End of 32-bit bitfield */ + + /* Start of 32-bit bitfield */ + + uint32_t beacon_tx_time : 24; /* Time of last beacon transmit */ + uint32_t min_be : 4; /* Min value of backoff exponent (BE) */ + uint32_t max_be : 4; /* Max value of backoff exponent (BE) */ + + /* End of 32-bit bitfield */ + + /* Start of 32-bit bitfield */ + + uint32_t tx_ctrl_active_dur : 17; /* Duration for which tx is permitted to + * be active */ + uint32_t tx_ctrl_pause_dur : 1; /* Duration after tx before another tx is + * permitted. 0=2000, 1= 10000 */ + uint32_t timestamp_support : 1; /* Does MAC layer supports timestamping */ + uint32_t is_coord : 1; /* Is this device acting as coordinator */ + /* 12-bits remaining */ + + /* End of 32-bit bitfield. */ + + /* TODO: Add Security-related MAC PIB attributes */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline int mac802154_takesem(sem_t *sem); +#define mac802154_givesem(s) sem_post(s); + +static void mac802154_txdone_worker(FAR void *arg); +static void mac802154_rxframe_worker(FAR void *arg); + +/* Internal Functions */ + +static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv); +static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv); + +/* IEEE 802.15.4 PHY Interface OPs */ + +static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb, + FAR struct ieee802154_txdesc_s *tx_desc, + FAR uint8_t *buf); + +static int mac802154_poll_gts(FAR const struct ieee802154_radiocb_s *radiocb, + FAR struct ieee802154_txdesc_s *tx_desc, + FAR uint8_t *buf); + +static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb, + FAR const struct ieee802154_txdesc_s *tx_desc); + +static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, + FAR struct ieee802154_rxdesc_s *rx_desc, + FAR struct iob_s *frame); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_semtake + * + * Description: + * Acquire the semaphore used for access serialization. + * + ****************************************************************************/ + +static inline int mac802154_takesem(sem_t *sem) +{ + /* Take a count from the semaphore, possibly waiting */ + + if (sem_wait(sem) < 0) + { + /* EINTR is the only error that we expect */ + + int errcode = get_errno(); + DEBUGASSERT(errcode == EINTR); + return -errcode; + } + + return OK; +} + +/**************************************************************************** + * Name: mac802154_defaultmib + * + * Description: + * Set the MIB to its default values. + * + ****************************************************************************/ + +static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv) +{ + /* TODO: Set all MAC fields to default values */ + + return OK; +} + +/**************************************************************************** + * Name: mac802154_applymib + * + * Description: + * Some parts of the MIB must be sent to the radio device. This routine + * calls the radio device routines to store the related parameters in the + * radio driver. It must be called each time a MIB parameter is changed. + * + ****************************************************************************/ + +static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv) +{ + return OK; +} + +/**************************************************************************** + * Name: mac802154_poll_csma + * + * Description: + * Called from the radio driver through the callback struct. This function is + * called when the radio has room for another CSMA transaction. If the MAC + * layer has a CSMA transaction, it copies it into the supplied buffer and + * returns the length. A descriptor is also populated with the transaction. + * + ****************************************************************************/ + +static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb, + FAR struct ieee802154_txdesc_s *tx_desc, + FAR uint8_t *buf) +{ + FAR struct mac802154_radiocb_s *cb = + (FAR struct mac802154_radiocb_s *)radiocb; + FAR struct ieee802154_privmac_s *priv; + FAR struct mac802154_trans_s *trans; + + DEBUGASSERT(cb != NULL && cb->priv != NULL); + priv = cb->priv; + + /* Get exclusive access to the driver structure. We don't care about any + * signals so if we see one, just go back to trying to get access again. + */ + + while (mac802154_takesem(&priv->exclsem) != 0); + + /* Check to see if there are any CSMA transactions waiting */ + + if (priv->csma_head) + { + /* Pop a CSMA transaction off the list */ + + trans = priv->csma_head; + priv->csma_head = priv->csma_head->flink; + + mac802154_givesem(&priv->exclsem); + + /* Setup the transmit descriptor */ + + tx_desc->handle = trans->msdu_handle; + + /* Copy the frame into the buffer */ + + memcpy(&buf[0], trans->mhr_buf, trans->mhr_len); + memcpy(&buf[trans->mhr_len], trans->d_buf, trans->d_len); + + /* Now that we've passed off the data, notify the waiting thread. + * NOTE: The transaction was allocated on the waiting thread's stack so + * it will be automatically deallocated when that thread awakens and + * returns. + */ + + sem_post(&trans->sem); + return (trans->mhr_len + trans->d_len); + } + + mac802154_givesem(&priv->exclsem); + return 0; +} + +/**************************************************************************** + * Name: mac802154_poll_gts + * + * Description: + * Called from the radio driver through the callback struct. This function is + * called when the radio has room for another GTS transaction. If the MAC + * layer has a GTS transaction, it copies it into the supplied buffer and + * returns the length. A descriptor is also populated with the transaction. + * + ****************************************************************************/ + +static int mac802154_poll_gts(FAR const struct ieee802154_radiocb_s *radiocb, + FAR struct ieee802154_txdesc_s *tx_desc, + FAR uint8_t *buf) +{ + FAR struct mac802154_radiocb_s *cb = + (FAR struct mac802154_radiocb_s *)radiocb; + FAR struct ieee802154_privmac_s *priv; + FAR struct mac802154_trans_s *trans; + int ret = 0; + + DEBUGASSERT(cb != NULL && cb->priv != NULL); + priv = cb->priv; + + /* Get exclusive access to the driver structure. We don't care about any + * signals so if we see one, just go back to trying to get access again. + */ + + while (mac802154_takesem(&priv->exclsem) != 0); + +#warning Missing logic. + + mac802154_givesem(&priv->exclsem); + + return 0; +} + +/**************************************************************************** + * Name: mac802154_txdone + * + * Description: + * Called from the radio driver through the callback struct. This function is + * called when the radio has completed a transaction. The txdesc passed gives + * provides information about the completed transaction including the original + * handle provided when the transaction was created and the status of the + * transaction. This function copies the descriptor and schedules work to + * handle the transaction without blocking the radio. + * + ****************************************************************************/ + +static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb, + FAR const struct ieee802154_txdesc_s *tx_desc) +{ + FAR struct mac802154_radiocb_s *cb = + (FAR struct mac802154_radiocb_s *)radiocb; + FAR struct ieee802154_privmac_s *priv; + + DEBUGASSERT(cb != NULL && cb->priv != NULL); + priv = cb->priv; + + /* Get exclusive access to the driver structure. We don't care about any + * signals so if we see one, just go back to trying to get access again. + */ + + while (mac802154_takesem(&priv->exclsem) != 0); + + /* Check to see if there is an available tx descriptor slot. If there is + * not we simply drop the notification */ + + if (priv->txdesc_count < CONFIG_IEEE802154_NTXDESC) + { + /* Copy the txdesc over and link it into our list */ + + memcpy(&priv->txdesc[priv->txdesc_count++], tx_desc, + sizeof(struct ieee802154_txdesc_s)); + } + else + { + wlinfo("MAC802154: No room for TX Desc.\n"); + } + + mac802154_givesem(&priv->exclsem); + + /* Schedule work with the work queue to process the completion further */ + + if (work_available(&priv->tx_work)) + { + work_queue(MAC802154_WORK, &priv->tx_work, mac802154_txdone_worker, + (FAR void *)priv, 0); + } +} + +/**************************************************************************** + * Name: mac802154_txdone_worker + * + * Description: + * Worker function scheduled from mac802154_txdone. This function pops any + * TX descriptors off of the list and calls the next highest layers callback + * to inform the layer of the completed transaction and the status of it. + * + ****************************************************************************/ + +static void mac802154_txdone_worker(FAR void *arg) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)arg; + int i = 0; + + /* Get exclusive access to the driver structure. We don't care about any + * signals so if we see one, just go back to trying to get access again. + */ + + while (mac802154_takesem(&priv->exclsem) != 0); + + /* For each pending TX descriptor, send an application callback */ + + for (i = 0; i < priv->txdesc_count; i++) + { + priv->cb->mcps_notify(priv->cb, IEEE802154_NOTIFY_CONF_DATA, + (FAR const union ieee802154_mcps_notify_u *) &priv->txdesc[i]); + } + + /* We've handled all the descriptors and no further desc could have been added + * since we have the struct locked */ + + priv->txdesc_count = 0; + + mac802154_givesem(&priv->exclsem); +} + +/**************************************************************************** + * Name: mac802154_rxframe + * + * Description: + * Called from the radio driver through the callback struct. This function is + * called when the radio has received a frame. The frame is passed in an iob, + * so that we can free it when we are done processing. A pointer to the RX + * descriptor is passed along with the iob, but it must be copied here as it + * is allocated directly on the caller's stack. We simply link the frame, + * copy the RX descriptor, and schedule a worker to process the frame later so + * that we do not hold up the radio. + * + ****************************************************************************/ + +static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, + FAR struct ieee802154_rxdesc_s *rx_desc, + FAR struct iob_s *frame) +{ + FAR struct mac802154_radiocb_s *cb = + (FAR struct mac802154_radiocb_s *)radiocb; + FAR struct ieee802154_privmac_s *priv; + FAR struct ieee802154_rxdesc_s *desc; + + DEBUGASSERT(cb != NULL && cb->priv != NULL); + priv = cb->priv; + + /* Get exclusive access to the driver structure. We don't care about any + * signals so if we see one, just go back to trying to get access again. + */ + + while (mac802154_takesem(&priv->exclsem) != 0); + + /* TODO: Copy the frame descriptor to some type of list */ + + /* Push the iob onto the tail of the frame list for processing */ + + priv->rxframes_tail->io_flink = frame; + priv->rxframes_tail = frame; + + mac802154_givesem(&priv->exclsem); + + /* Schedule work with the work queue to process the completion further */ + + if (work_available(&priv->rx_work)) + { + work_queue(MAC802154_WORK, &priv->rx_work, mac802154_rxframe_worker, + (FAR void *)priv, 0); + } +} + +/**************************************************************************** + * Name: mac802154_rxframe_worker + * + * Description: + * Worker function scheduled from mac802154_rxframe. This function processes + * any frames in the list. Frames intended to be consumed by the MAC layer + * will not produce any callbacks to the next highest layer. Frames intended + * for the application layer will be forwarded to them. + * + ****************************************************************************/ + +static void mac802154_rxframe_worker(FAR void *arg) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)arg; + + /* The radio layer is responsible for handling all ACKs and retries. If for + * some reason an ACK gets here, just throw it out. + */ +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_create + * + * Description: + * Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. + * + * The returned MAC structure should be passed to either the next highest + * layer in the network stack, or registered with a mac802154dev character + * or network drivers. In any of these scenarios, the next highest layer + * should register a set of callbacks with the MAC layer by setting the + * mac->cbs member. + * + * NOTE: This API does not create any device accessible to userspace. If + * you want to call these APIs from userspace, you have to wrap your mac + * in a character device via mac802154_device.c. + * + * Input Parameters: + * radiodev - an instance of an IEEE 802.15.4 radio + * + * Returned Value: + * An opaque reference to the MAC state data. + * + ****************************************************************************/ + +MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) +{ + FAR struct ieee802154_privmac_s *mac; + FAR struct ieee802154_radiocb_s *radiocb; + + /* Allocate object */ + + mac = (FAR struct ieee802154_privmac_s *) + kmm_zalloc(sizeof(struct ieee802154_privmac_s)); + + if (mac == NULL) + { + return NULL; + } + + /* Initialize fields */ + + mac->radio = radiodev; + + mac802154_defaultmib(mac); + mac802154_applymib(mac); + + /* Initialize the Radio callbacks */ + + mac->radiocb.priv = mac; + + radiocb = &mac->radiocb.cb; + radiocb->poll_csma = mac802154_poll_csma; + radiocb->poll_gts = mac802154_poll_gts; + radiocb->txdone = mac802154_txdone; + radiocb->rxframe = mac802154_rxframe; + + /* Bind our callback structure */ + + radiodev->ops->bind(radiodev, &mac->radiocb.cb); + + return (MACHANDLE)mac; +} + +/**************************************************************************** + * Name: mac802154_bind + * + * Description: + * Bind the MAC callback table to the MAC state. + * + * Parameters: + * mac - Reference to the MAC driver state structure + * cb - MAC callback operations + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int mac802154_bind(MACHANDLE mac, FAR const struct ieee802154_maccb_s *cb) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + + priv->cb = cb; + return OK; +} + +/**************************************************************************** + * Name: mac802154_ioctl + * + * Description: + * Handle MAC and radio IOCTL commands directed to the MAC. + * + * Parameters: + * mac - Reference to the MAC driver state structure + * cmd - The IOCTL command + * arg - The argument for the IOCTL command + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret = -EINVAL; + + DEBUGASSERT(priv != NULL); + + /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */ + + if (_MAC802154IOCVALID(cmd)) + { + /* Handle the MAC IOCTL command */ +#warning Missing logic + } + + /* No, other IOCTLs must be aimed at the IEEE802.15.4 radio layer */ + + else + { + DEBUGASSERT(priv->radio != NULL && + priv->radio->ops != NULL && + priv->radio->ops->ioctl != NULL); + + ret = priv->radio->ops->ioctl(priv->radio, cmd, arg); + } + + return ret; +} + +/**************************************************************************** + * MAC Interface Operations + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_data + * + * Description: + * The MCPS-DATA.request primitive requests the transfer of a data SPDU + * (i.e., MSDU) from a local SSCS entity to a single peer SSCS entity. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_data callback. + * + ****************************************************************************/ + +int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + FAR struct mac802154_trans_s trans; + struct mac802154_unsec_mhr_s mhr; + int ret; + + /* Start off assuming there is only the frame_control field in the MHR */ + + mhr.length = 2; + + /* Do a preliminary check to make sure the MSDU isn't too long for even + * the best case. + */ + + if (req->msdu_length > IEEE802154_MAX_MAC_PAYLOAD_SIZE) + { + return -EINVAL; + } + + /* Ensure we start with a clear frame control field */ + + mhr.u.frame_control = 0; + + /* Set the frame type to Data */ + + mhr.u.frame_control |= IEEE802154_FRAME_DATA << + IEEE802154_FRAMECTRL_SHIFT_FTYPE; + + /* If the msduLength is greater than aMaxMACSafePayloadSize, the MAC + * sublayer will set the Frame Version to one. [1] pg. 118. + */ + + if (req->msdu_length > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) + { + mhr.u.frame_control |= IEEE802154_FRAMECTRL_VERSION; + } + + /* If the TXOptions parameter specifies that an acknowledged transmission + * is required, the AR field will be set appropriately, as described in + * 5.1.6.4 [1] pg. 118. + */ + + mhr.u.frame_control |= (req->msdu_flags.ack_tx << + IEEE802154_FRAMECTRL_SHIFT_ACKREQ); + + /* If the destination address is present, copy the PAN ID and one of the + * addresses, depending on mode, into the MHR . + */ + + if (req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + { + memcpy(&mhr.u.data[mhr.length], &req->dest_addr.panid, 2); + mhr.length += 2; + + if (req->dest_addr.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&mhr.u.data[mhr.length], &req->dest_addr.saddr, 2); + mhr.length += 2; + } + else if (req->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&mhr.u.data[mhr.length], &req->dest_addr.eaddr, 8); + mhr.length += 8; + } + } + + /* Set the destination addr mode inside the frame contorl field */ + + mhr.u.frame_control |= (req->dest_addr.mode << + IEEE802154_FRAMECTRL_SHIFT_DADDR); + + /* From this point on, we need exclusive access to the privmac struct */ + + ret = mac802154_takesem(&priv->exclsem); + if (ret < 0) + { + wlerr("ERROR: mac802154_takesem failed: %d\n", ret); + return ret; + } + + /* If both destination and source addressing information is present, the MAC + * sublayer shall compare the destination and source PAN identifiers. + * [1] pg. 41. + */ + + if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE && + req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + { + /* If the PAN identifiers are identical, the PAN ID Compression field + * shall be set to one, and the source PAN identifier shall be omitted + * from the transmitted frame. [1] pg. 41. + */ + + if (req->dest_addr.panid == priv->addr.panid) + { + mhr.u.frame_control |= IEEE802154_FRAMECTRL_PANIDCOMP; + } + } + + if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE) + { + /* If the destination address is not included, or if PAN ID Compression + * is off, we need to include the Source PAN ID. + */ + + if ((req->dest_addr.mode == IEEE802154_ADDRMODE_NONE) || + (mhr.u.frame_control & IEEE802154_FRAMECTRL_PANIDCOMP)) + { + memcpy(&mhr.u.data[mhr.length], &priv->addr.panid, 2); + mhr.length += 2; + } + + if (req->src_addr_mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&mhr.u.data[mhr.length], &priv->addr.saddr, 2); + mhr.length += 2; + } + else if (req->src_addr_mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&mhr.u.data[mhr.length], &priv->addr.eaddr, 8); + mhr.length += 8; + } + } + + /* Set the source addr mode inside the frame control field */ + + mhr.u.frame_control |= (req->src_addr_mode << + IEEE802154_FRAMECTRL_SHIFT_SADDR); + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the MHR + * of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + mhr.u.data[mhr.length++] = priv->dsn++; + + /* Now that we know which fields are included in the header, we can make + * sure we actually have enough room in the PSDU. + */ + + if (mhr.length + req->msdu_length + IEEE802154_MFR_LENGTH > + IEEE802154_MAX_PHY_PACKET_SIZE) + { + return -E2BIG; + } + + trans.mhr_buf = &mhr.u.data[0]; + trans.mhr_len = mhr.length; + + trans.d_buf = &req->msdu[0]; + trans.d_len = req->msdu_length; + + trans.msdu_handle = req->msdu_handle; + + /* If the TxOptions parameter specifies that a GTS transmission is required, + * the MAC sublayer will determine whether it has a valid GTS as described + * 5.1.7.3. If a valid GTS could not be found, the MAC sublayer will discard + * the MSDU. If a valid GTS was found, the MAC sublayer will defer, if + * necessary, until the GTS. If the TxOptions parameter specifies that a GTS + * transmission is not required, the MAC sublayer will transmit the MSDU using + * either slotted CSMA-CA in the CAP for a beacon-enabled PAN or unslotted + * CSMA-CA for a nonbeacon-enabled PAN. Specifying a GTS transmission in the + * TxOptions parameter overrides an indirect transmission request. + * [1] pg. 118. + */ + + if (req->msdu_flags.gts_tx) + { + /* TODO: Support GTS transmission. This should just change where we link + * the transaction. Instead of going in the CSMA transaction list, it + * should be linked to the GTS' transaction list. We'll need to check if + * the GTS is valid, and then find the GTS, before linking. Note, we also + * don't have to try and kick-off any transmission here. + */ + + return -ENOTSUP; + } + else + { + /* If the TxOptions parameter specifies that an indirect transmission is + * required and this primitive is received by the MAC sublayer of a + * coordinator, the data frame is sent using indirect transmission, as + * described in 5.1.5 and 5.1.6.3. [1] + */ + + if (req->msdu_flags.indirect_tx) + { + /* If the TxOptions parameter specifies that an indirect transmission + * is required and if the device receiving this primitive is not a + * coordinator, the destination address is not present, or the + * TxOptions parameter also specifies a GTS transmission, the indirect + * transmission option will be ignored. [1] + */ + + if (priv->is_coord && req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + { + /* Link the transaction into the indirect_trans list */ + + priv->indirect_tail->flink = &trans; + priv->indirect_tail = &trans; + } + else + { + /* Override the setting since it wasn't valid */ + + req->msdu_flags.indirect_tx = 0; + } + } + + /* If this is a direct transmission not during a GTS */ + + if (!req->msdu_flags.indirect_tx) + { + /* Link the transaction into the CSMA transaction list */ + + priv->csma_tail->flink = &trans; + priv->csma_tail = &trans; + + /* We no longer need to have the MAC layer locked. */ + + mac802154_givesem(&priv->exclsem); + + /* Notify the radio driver that there is data available */ + + priv->radio->ops->txnotify_csma(priv->radio); + + sem_wait(&trans.sem); + } + } + + return OK; +} + + +/**************************************************************************** + * Name: mac802154_req_purge + * + * Description: + * The MCPS-PURGE.request primitive allows the next higher layer to purge + * an MSDU from the transaction queue. Confirmation is returned via + * the struct ieee802154_maccb_s->conf_purge callback. + * + ****************************************************************************/ + +int mac802154_req_purge(MACHANDLE mac, FAR struct ieee802154_purge_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_associate + * + * Description: + * The MLME-ASSOCIATE.request primitive allows a device to request an + * association with a coordinator. Confirmation is returned via the + * struct ieee802154_maccb_s->conf_associate callback. + * + ****************************************************************************/ + +int mac802154_req_associate(MACHANDLE mac, + FAR struct ieee802154_assoc_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + + /* Set the channel of the PHY layer */ + + /* Set the channel page of the PHY layer */ + + /* Set the macPANId */ + + /* Set either the macCoordExtendedAddress and macCoordShortAddress + * depending on the CoordAddrMode in the primitive. + */ + + if (req->coord_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + + } + else if (req->coord_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + + } + else + { + return -EINVAL; + } + + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_disassociate + * + * Description: + * The MLME-DISASSOCIATE.request primitive is used by an associated device to + * notify the coordinator of its intent to leave the PAN. It is also used by + * the coordinator to instruct an associated device to leave the PAN. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_disassociate callback. + * + ****************************************************************************/ + +int mac802154_req_disassociate(MACHANDLE mac, + FAR struct ieee802154_disassoc_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_get + * + * Description: + * The MLME-GET.request primitive requests information about a given PIB + * attribute. Actual data is returned via the + * struct ieee802154_maccb_s->conf_get callback. + * + ****************************************************************************/ + +int mac802154_req_get(MACHANDLE mac, FAR struct ieee802154_get_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_gts + * + * Description: + * The MLME-GTS.request primitive allows a device to send a request to the PAN + * coordinator to allocate a new GTS or to deallocate an existing GTS. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_gts callback. + * + ****************************************************************************/ + +int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_reset + * + * Description: + * The MLME-RESET.request primitive allows the next higher layer to request + * that the MLME performs a reset operation. Confirmation is returned via + * the struct ieee802154_maccb_s->conf_reset callback. + * + ****************************************************************************/ + +int mac802154_req_reset(MACHANDLE mac, FAR struct ieee802154_reset_req_s *req) +{ + FAR struct ieee802154_privmac_s * priv = + (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_rxenable + * + * Description: + * The MLME-RX-ENABLE.request primitive allows the next higher layer to + * request that the receiver is enable for a finite period of time. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_rxenable callback. + * + ****************************************************************************/ + +int mac802154_req_rxenable(MACHANDLE mac, + FAR struct ieee802154_rxenable_req_s *req) +{ + FAR struct ieee802154_privmac_s * priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_scan + * + * Description: + * The MLME-SCAN.request primitive is used to initiate a channel scan over a + * given list of channels. A device can use a channel scan to measure the + * energy on the channel, search for the coordinator with which it associated, + * or search for all coordinators transmitting beacon frames within the POS of + * the scanning device. Scan results are returned + * via MULTIPLE calls to the struct ieee802154_maccb_s->conf_scan callback. + * This is a difference with the official 802.15.4 specification, implemented + * here to save memory. + * + ****************************************************************************/ + +int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_set + * + * Description: + * The MLME-SET.request primitive attempts to write the given value to the + * indicated MAC PIB attribute. Confirmation is returned via the + * struct ieee802154_maccb_s->conf_set callback. + * + ****************************************************************************/ + +int mac802154_req_set(MACHANDLE mac, FAR struct ieee802154_set_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_start + * + * Description: + * The MLME-START.request primitive makes a request for the device to start + * using a new superframe configuration. Confirmation is returned + * via the struct ieee802154_maccb_s->conf_start callback. + * + ****************************************************************************/ + +int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_sync + * + * Description: + * The MLME-SYNC.request primitive requests to synchronize with the + * coordinator by acquiring and, if specified, tracking its beacons. + * Confirmation is returned via the + * struct ieee802154_maccb_s->int_commstatus callback. TOCHECK. + * + ****************************************************************************/ + +int mac802154_req_sync(MACHANDLE mac, FAR struct ieee802154_sync_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_req_poll + * + * Description: + * The MLME-POLL.request primitive prompts the device to request data from + * the coordinator. Confirmation is returned via the + * struct ieee802154_maccb_s->conf_poll callback, followed by a + * struct ieee802154_maccb_s->ind_data callback. + * + ****************************************************************************/ + +int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_rsp_associate + * + * Description: + * The MLME-ASSOCIATE.response primitive is used to initiate a response to + * an MLME-ASSOCIATE.indication primitive. + * + ****************************************************************************/ + +int mac802154_rsp_associate(MACHANDLE mac, + FAR struct ieee802154_assoc_resp_s *resp) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_rsp_orphan + * + * Description: + * The MLME-ORPHAN.response primitive allows the next higher layer of a + * coordinator to respond to the MLME-ORPHAN.indication primitive. + * + ****************************************************************************/ + +int mac802154_rsp_orphan(MACHANDLE mac, + FAR struct ieee802154_orphan_resp_s *resp) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} diff --git a/wireless/ieee802154/mac802154.h b/wireless/ieee802154/mac802154.h index 3b2cd1de5a..00235d025b 100644 --- a/wireless/ieee802154/mac802154.h +++ b/wireless/ieee802154/mac802154.h @@ -120,7 +120,7 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req); * ****************************************************************************/ -int mac802154_req_purge(MACHANDLE mac, uint8_t handle); +int mac802154_req_purge(MACHANDLE mac, FAR struct ieee802154_purge_req_s *req); /**************************************************************************** * Name: mac802154_req_associate @@ -162,7 +162,7 @@ int mac802154_req_disassociate(MACHANDLE mac, * ****************************************************************************/ -int mac802154_req_get(MACHANDLE mac, enum ieee802154_pib_attr_e attr); +int mac802154_req_get(MACHANDLE mac, FAR struct ieee802154_get_req_s *req); /**************************************************************************** * Name: mac802154_req_gts @@ -175,7 +175,7 @@ int mac802154_req_get(MACHANDLE mac, enum ieee802154_pib_attr_e attr); * ****************************************************************************/ -int mac802154_req_gts(MACHANDLE mac, FAR uint8_t *characteristics); +int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req); /**************************************************************************** * Name: mac802154_req_reset @@ -187,7 +187,7 @@ int mac802154_req_gts(MACHANDLE mac, FAR uint8_t *characteristics); * ****************************************************************************/ -int mac802154_req_reset(MACHANDLE mac, bool setdefaults); +int mac802154_req_reset(MACHANDLE mac, FAR struct ieee802154_reset_req_s *req); /**************************************************************************** * Name: mac802154_req_rxenable @@ -200,8 +200,8 @@ int mac802154_req_reset(MACHANDLE mac, bool setdefaults); * ****************************************************************************/ -int mac802154_req_rxenable(MACHANDLE mac, bool deferrable, int ontime, - int duration); +int mac802154_req_rxenable(MACHANDLE mac, + FAR struct ieee802154_rxenable_req_s *req); /**************************************************************************** * Name: mac802154_req_scan @@ -218,8 +218,7 @@ int mac802154_req_rxenable(MACHANDLE mac, bool deferrable, int ontime, * ****************************************************************************/ -int mac802154_req_scan(MACHANDLE mac, uint8_t type, uint32_t channels, - int duration); +int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req); /**************************************************************************** * Name: mac802154_req_set @@ -231,8 +230,7 @@ int mac802154_req_scan(MACHANDLE mac, uint8_t type, uint32_t channels, * ****************************************************************************/ -int mac802154_req_set(MACHANDLE mac, int attribute, FAR uint8_t *value, - int valuelen); +int mac802154_req_set(MACHANDLE mac, FAR struct ieee802154_set_req_s *req); /**************************************************************************** * Name: mac802154_req_start @@ -244,9 +242,7 @@ int mac802154_req_set(MACHANDLE mac, int attribute, FAR uint8_t *value, * ****************************************************************************/ -int mac802154_req_start(MACHANDLE mac, uint16_t panid, int channel, - uint8_t bo, uint8_t fo, bool coord, bool batext, - bool realign); +int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req); /**************************************************************************** * Name: mac802154_req_sync @@ -259,7 +255,7 @@ int mac802154_req_start(MACHANDLE mac, uint16_t panid, int channel, * ****************************************************************************/ -int mac802154_req_sync(MACHANDLE mac, int channel, bool track); +int mac802154_req_sync(MACHANDLE mac, FAR struct ieee802154_sync_req_s *req); /**************************************************************************** * Name: mac802154_req_poll @@ -272,7 +268,7 @@ int mac802154_req_sync(MACHANDLE mac, int channel, bool track); * ****************************************************************************/ -int mac802154_req_poll(MACHANDLE mac, FAR uint8_t *coordaddr); +int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req); /**************************************************************************** * Name: mac802154_rsp_associate @@ -283,8 +279,8 @@ int mac802154_req_poll(MACHANDLE mac, FAR uint8_t *coordaddr); * ****************************************************************************/ -int mac802154_rsp_associate(MACHANDLE mac, uint8_t eadr, uint16_t saddr, - int status); +int mac802154_rsp_associate(MACHANDLE mac, + FAR struct ieee802154_assoc_resp_s *resp); /**************************************************************************** * Name: mac802154_rsp_orphan @@ -295,8 +291,8 @@ int mac802154_rsp_associate(MACHANDLE mac, uint8_t eadr, uint16_t saddr, * ****************************************************************************/ -int mac802154_rsp_orphan(MACHANDLE mac, FAR uint8_t *orphanaddr, - uint16_t saddr, bool associated); +int mac802154_rsp_orphan(MACHANDLE mac, + FAR struct ieee802154_orphan_resp_s *resp); #undef EXTERN #ifdef __cplusplus diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index 6370ff4762..19d3a5bc41 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -139,6 +139,14 @@ struct mac802154_chardevice_s static inline int mac802154dev_takesem(sem_t *sem); #define mac802154dev_givesem(s) sem_post(s); +static void mac802154dev_mlme_notify(FAR const struct ieee802154_maccb_s *maccb, + enum ieee802154_macnotify_e notif, + FAR const union ieee802154_mlme_notify_u *arg); + +static void mac802154dev_mcps_notify(FAR const struct ieee802154_maccb_s *maccb, + enum ieee802154_macnotify_e notif, + FAR const union ieee802154_mcps_notify_u *arg); + static int mac802154dev_open(FAR struct file *filep); static int mac802154dev_close(FAR struct file *filep); static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer, @@ -151,7 +159,7 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, /* MAC callback helpers */ static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev, - FAR struct ieee802154_data_conf_s *conf); + FAR const struct ieee802154_data_conf_s *conf); /**************************************************************************** * Private Data @@ -591,9 +599,9 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, return ret; } -static void mac802154dev_mlme_notify(FAR struct ieee802154_maccb_s *maccb, +static void mac802154dev_mlme_notify(FAR const struct ieee802154_maccb_s *maccb, enum ieee802154_macnotify_e notif, - FAR union ieee802154_mlme_notify_u *arg) + FAR const union ieee802154_mlme_notify_u *arg) { FAR struct mac802154dev_callback_s *cb = (FAR struct mac802154dev_callback_s *)maccb; @@ -610,9 +618,9 @@ static void mac802154dev_mlme_notify(FAR struct ieee802154_maccb_s *maccb, } } -static void mac802154dev_mcps_notify(FAR struct ieee802154_maccb_s *maccb, +static void mac802154dev_mcps_notify(FAR const struct ieee802154_maccb_s *maccb, enum ieee802154_macnotify_e notif, - FAR union ieee802154_mcps_notify_u *arg) + FAR const union ieee802154_mcps_notify_u *arg) { FAR struct mac802154dev_callback_s *cb = (FAR struct mac802154dev_callback_s *)maccb; @@ -634,7 +642,7 @@ static void mac802154dev_mcps_notify(FAR struct ieee802154_maccb_s *maccb, } static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev, - FAR struct ieee802154_data_conf_s *conf) + FAR const struct ieee802154_data_conf_s *conf) { FAR struct mac802154dev_dwait_s *curr; FAR struct mac802154dev_dwait_s *prev; @@ -647,7 +655,7 @@ static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev, /* Search to see if there is a dwait pending for this transaction */ for (prev = NULL, curr = dev->md_dwait; - curr && curr->mw_handle != conf->msdu_handle; + curr && curr->mw_handle != conf->handle; prev = curr, curr = curr->mw_flink); /* If a dwait is found */ @@ -669,7 +677,7 @@ static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev, /* Copy the transmission status into the dwait struct */ - curr->mw_status = conf->msdu_handle; + curr->mw_status = conf->status; /* Wake the thread waiting for the data transmission */ diff --git a/wireless/ieee802154/radio802154_device.c b/wireless/ieee802154/radio802154_device.c index a1fe8dc515..2c48e107d0 100644 --- a/wireless/ieee802154/radio802154_device.c +++ b/wireless/ieee802154/radio802154_device.c @@ -254,13 +254,13 @@ static ssize_t radio802154dev_read(FAR struct file *filep, FAR char *buffer, siz goto done; } - ret = dev->child->ops->rxenable(dev->child, 1, buf); +#warning Receive needs to be redone! #if 0 + ret = dev->child->ops->rxenable(dev->child, 1, buf); if (ret < 0) { goto done; } -#endif /* if no packet is received, this will produce -EAGAIN * The user is responsible for sleeping until sth arrives @@ -282,6 +282,8 @@ static ssize_t radio802154dev_read(FAR struct file *filep, FAR char *buffer, siz dev->child->ops->rxenable(dev->child, 0, NULL); ret = buf->len; +#endif + done: return ret; }