diff --git a/drivers/ieee802154/ieee802154_cc1200.c b/drivers/ieee802154/ieee802154_cc1200.c index 158fe91e683..195a44017d3 100644 --- a/drivers/ieee802154/ieee802154_cc1200.c +++ b/drivers/ieee802154/ieee802154_cc1200.c @@ -592,6 +592,7 @@ static int cc1200_set_txpower(struct device *dev, s16_t dbm) } static int cc1200_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) { @@ -600,6 +601,11 @@ static int cc1200_tx(struct device *dev, u8_t len = frag->len; bool status = false; + if (mode != IEEE802154_TX_MODE_DIRECT) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + LOG_DBG("%p (%u)", frag, len); /* ToDo: diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c index 4cff57b2090..e346d72e19f 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c @@ -188,7 +188,9 @@ static int ieee802154_cc13xx_cc26xx_set_txpower(struct device *dev, s16_t dbm) } /* See IEEE 802.15.4 section 6.2.5.1 and TRM section 25.5.4.3 */ -static int ieee802154_cc13xx_cc26xx_tx(struct device *dev, struct net_pkt *pkt, +static int ieee802154_cc13xx_cc26xx_tx(struct device *dev, + enum ieee802154_tx_mode mode, + struct net_pkt *pkt, struct net_buf *frag) { struct ieee802154_cc13xx_cc26xx_data *drv_data = get_dev_data(dev); @@ -196,6 +198,11 @@ static int ieee802154_cc13xx_cc26xx_tx(struct device *dev, struct net_pkt *pkt, int retry = CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES; u32_t status; + if (mode != IEEE802154_TX_MODE_CSMA_CA) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + drv_data->cmd_ieee_csma.status = IDLE; drv_data->cmd_ieee_csma.randomState = sys_rand32_get(); diff --git a/drivers/ieee802154/ieee802154_cc2520.c b/drivers/ieee802154/ieee802154_cc2520.c index d44fa4e8ead..bd4eef0c093 100644 --- a/drivers/ieee802154/ieee802154_cc2520.c +++ b/drivers/ieee802154/ieee802154_cc2520.c @@ -793,6 +793,7 @@ error: } static int cc2520_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) { @@ -802,6 +803,11 @@ static int cc2520_tx(struct device *dev, u8_t retry = 2U; bool status; + if (mode != IEEE802154_TX_MODE_DIRECT) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + LOG_DBG("%p (%u)", frag, len); if (!write_reg_excflag0(cc2520, EXCFLAG0_RESET_TX_FLAGS) || diff --git a/drivers/ieee802154/ieee802154_kw41z.c b/drivers/ieee802154/ieee802154_kw41z.c index 3bcc332a183..6e39fe337cc 100644 --- a/drivers/ieee802154/ieee802154_kw41z.c +++ b/drivers/ieee802154/ieee802154_kw41z.c @@ -612,8 +612,8 @@ out: net_pkt_unref(ack_pkt); } -static int kw41z_tx(struct device *dev, struct net_pkt *pkt, - struct net_buf *frag) +static int kw41z_tx(struct device *dev, enum ieee802154_tx_mode mode, + struct net_pkt *pkt, struct net_buf *frag) { struct kw41z_context *kw41z = dev->driver_data; u8_t payload_len = frag->len; @@ -621,6 +621,11 @@ static int kw41z_tx(struct device *dev, struct net_pkt *pkt, u8_t xcvseq; int key; + if (mode != IEEE802154_TX_MODE_DIRECT) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + /* * The transmit requests are preceded by the CCA request. On * completion of the CCA the sequencer should be in the IDLE diff --git a/drivers/ieee802154/ieee802154_mcr20a.c b/drivers/ieee802154/ieee802154_mcr20a.c index a56a9de3916..d7e931375b7 100644 --- a/drivers/ieee802154/ieee802154_mcr20a.c +++ b/drivers/ieee802154/ieee802154_mcr20a.c @@ -1082,6 +1082,7 @@ static inline bool write_txfifo_content(struct mcr20a_context *dev, } static int mcr20a_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) { @@ -1090,6 +1091,11 @@ static int mcr20a_tx(struct device *dev, MCR20A_XCVSEQ_TX; int retval; + if (mode != IEEE802154_TX_MODE_DIRECT) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + k_mutex_lock(&mcr20a->phy_mutex, K_FOREVER); LOG_DBG("%p (%u)", frag, frag->len); diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 313dfe8815d..8e3c11f5903 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -322,6 +322,7 @@ free_nrf_ack: } static int nrf5_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) { @@ -329,6 +330,11 @@ static int nrf5_tx(struct device *dev, u8_t payload_len = frag->len; u8_t *payload = frag->data; + if (mode != IEEE802154_TX_MODE_DIRECT) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + LOG_DBG("%p (%u)", payload, payload_len); nrf5_radio->tx_psdu[0] = payload_len + NRF5_FCS_LENGTH; diff --git a/drivers/ieee802154/ieee802154_rf2xx.c b/drivers/ieee802154/ieee802154_rf2xx.c index 9926aecc89f..eeafb6a464b 100644 --- a/drivers/ieee802154/ieee802154_rf2xx.c +++ b/drivers/ieee802154/ieee802154_rf2xx.c @@ -473,6 +473,7 @@ static void rf2xx_handle_ack(struct rf2xx_context *ctx, struct net_buf *frag) #endif static int rf2xx_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) { @@ -481,6 +482,11 @@ static int rf2xx_tx(struct device *dev, struct rf2xx_context *ctx = dev->driver_data; int response = 0; + if (mode != IEEE802154_TX_MODE_CSMA_CA) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + rf2xx_trx_set_tx_state(dev); rf2xx_iface_reg_read(dev, RF2XX_IRQ_STATUS_REG); diff --git a/drivers/ieee802154/ieee802154_uart_pipe.c b/drivers/ieee802154/ieee802154_uart_pipe.c index e695fa275cd..14da9e13db8 100644 --- a/drivers/ieee802154/ieee802154_uart_pipe.c +++ b/drivers/ieee802154/ieee802154_uart_pipe.c @@ -266,6 +266,7 @@ static int upipe_set_txpower(struct device *dev, s16_t dbm) } static int upipe_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) { @@ -274,6 +275,11 @@ static int upipe_tx(struct device *dev, u8_t len = frag->len; u8_t i, data; + if (mode != IEEE802154_TX_MODE_DIRECT) { + NET_ERR("TX mode %d not supported", mode); + return -ENOTSUP; + } + LOG_DBG("%p (%u)", frag, len); if (upipe->stopped) { diff --git a/include/net/ieee802154_radio.h b/include/net/ieee802154_radio.h index f01a178390c..1219a14c58a 100644 --- a/include/net/ieee802154_radio.h +++ b/include/net/ieee802154_radio.h @@ -36,7 +36,8 @@ enum ieee802154_hw_caps { IEEE802154_HW_2_4_GHZ = BIT(4), /* 2.4Ghz radio supported */ IEEE802154_HW_TX_RX_ACK = BIT(5), /* Handles ACK request on TX */ IEEE802154_HW_SUB_GHZ = BIT(6), /* Sub-GHz radio supported */ - IEEE802154_HW_ENERGY_SCAN = BIT(7) /* Energy scan supported */ + IEEE802154_HW_ENERGY_SCAN = BIT(7), /* Energy scan supported */ + IEEE802154_HW_TXTIME = BIT(8), /* TX at specified time supported */ }; enum ieee802154_filter_type { @@ -57,6 +58,24 @@ struct ieee802154_filter { /* @endcond */ }; +/** IEEE802.15.4 Transmission mode. */ +enum ieee802154_tx_mode { + /** Transmit packet immediately, no CCA. */ + IEEE802154_TX_MODE_DIRECT, + + /** Perform CCA before packet transmission. */ + IEEE802154_TX_MODE_CCA, + + /** Perform full CSMA CA procedure before packet transmission. */ + IEEE802154_TX_MODE_CSMA_CA, + + /** Transmit packet in the future, at specified time, no CCA. */ + IEEE802154_TX_MODE_TXTIME, + + /** Transmit packet in the future, perform CCA before transmission. */ + IEEE802154_TX_MODE_TXTIME_CCA, +}; + /** IEEE802.15.4 driver configuration types. */ enum ieee802154_config_type { /** Indicates how radio driver should set Frame Pending bit in ACK @@ -137,9 +156,8 @@ struct ieee802154_radio_api { int (*set_txpower)(struct device *dev, s16_t dbm); /** Transmit a packet fragment */ - int (*tx)(struct device *dev, - struct net_pkt *pkt, - struct net_buf *frag); + int (*tx)(struct device *dev, enum ieee802154_tx_mode mode, + struct net_pkt *pkt, struct net_buf *frag); /** Start the device */ int (*start)(struct device *dev); diff --git a/samples/net/wpan_serial/src/main.c b/samples/net/wpan_serial/src/main.c index 0183f8203f1..d21f43e552b 100644 --- a/samples/net/wpan_serial/src/main.c +++ b/samples/net/wpan_serial/src/main.c @@ -248,7 +248,8 @@ static void process_data(struct net_pkt *pkt) } /* Transmit data through radio */ - ret = radio_api->tx(ieee802154_dev, pkt, buf); + ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT, + pkt, buf); if (ret) { LOG_ERR("Error transmit data"); } diff --git a/samples/net/wpanusb/src/wpanusb.c b/samples/net/wpanusb/src/wpanusb.c index de8688f172f..342c3d674b1 100644 --- a/samples/net/wpanusb/src/wpanusb.c +++ b/samples/net/wpanusb/src/wpanusb.c @@ -260,7 +260,8 @@ static int tx(struct net_pkt *pkt) LOG_DBG("len %d seq %u", buf->len, seq); do { - ret = radio_api->tx(ieee802154_dev, pkt, buf); + ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT, + pkt, buf); } while (ret && retries--); if (ret) { diff --git a/subsys/net/l2/ieee802154/ieee802154.c b/subsys/net/l2/ieee802154/ieee802154.c index f20bdaf11d3..c6c6f7cb2c5 100644 --- a/subsys/net/l2/ieee802154/ieee802154.c +++ b/subsys/net/l2/ieee802154/ieee802154.c @@ -81,7 +81,8 @@ static inline void ieee802154_acknowledge(struct net_if *iface, } if (ieee802154_create_ack_frame(iface, pkt, mpdu->mhr.fs->sequence)) { - ieee802154_tx(iface, pkt, pkt->buffer); + ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT, + pkt, pkt->buffer); } net_pkt_unref(pkt); @@ -276,7 +277,8 @@ static int ieee802154_send(struct net_if *iface, struct net_pkt *pkt) if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) && ieee802154_get_hw_capabilities(iface) & IEEE802154_HW_CSMA) { - ret = ieee802154_tx(iface, pkt, &frame_buf); + ret = ieee802154_tx(iface, IEEE802154_TX_MODE_CSMA_CA, + pkt, &frame_buf); } else { ret = ieee802154_radio_send(iface, pkt, &frame_buf); } diff --git a/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c b/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c index 837b9083bd5..c70a3398c1d 100644 --- a/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c +++ b/subsys/net/l2/ieee802154/ieee802154_radio_aloha.c @@ -30,7 +30,8 @@ static inline int aloha_radio_send(struct net_if *iface, while (retries) { retries--; - ret = ieee802154_tx(iface, pkt, frag); + ret = ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT, + pkt, frag); if (ret) { continue; } diff --git a/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c b/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c index ed653e8e865..6afe3638a0d 100644 --- a/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c +++ b/subsys/net/l2/ieee802154/ieee802154_radio_csma_ca.c @@ -57,7 +57,8 @@ loop: } } - ret = ieee802154_tx(iface, pkt, frag); + ret = ieee802154_tx(iface, IEEE802154_TX_MODE_DIRECT, + pkt, frag); if (ret) { continue; } diff --git a/subsys/net/l2/ieee802154/ieee802154_utils.h b/subsys/net/l2/ieee802154/ieee802154_utils.h index bfffe9687ad..e950a9f47f7 100644 --- a/subsys/net/l2/ieee802154/ieee802154_utils.h +++ b/subsys/net/l2/ieee802154/ieee802154_utils.h @@ -64,7 +64,9 @@ static inline int ieee802154_set_tx_power(struct net_if *iface, s16_t dbm) } static inline int ieee802154_tx(struct net_if *iface, - struct net_pkt *pkt, struct net_buf *buf) + enum ieee802154_tx_mode mode, + struct net_pkt *pkt, + struct net_buf *buf) { const struct ieee802154_radio_api *radio = net_if_get_device(iface)->driver_api; @@ -73,7 +75,7 @@ static inline int ieee802154_tx(struct net_if *iface, return -ENOENT; } - return radio->tx(net_if_get_device(iface), pkt, buf); + return radio->tx(net_if_get_device(iface), mode, pkt, buf); } static inline int ieee802154_start(struct net_if *iface) diff --git a/subsys/net/lib/openthread/platform/radio.c b/subsys/net/lib/openthread/platform/radio.c index 6752dbeed00..14d209fa0f5 100644 --- a/subsys/net/lib/openthread/platform/radio.c +++ b/subsys/net/lib/openthread/platform/radio.c @@ -190,11 +190,13 @@ void platformRadioProcess(otInstance *aInstance) if (sTransmitFrame.mInfo.mTxInfo.mCsmaCaEnabled) { if (radio_api->cca(radio_dev) || - radio_api->tx(radio_dev, tx_pkt, tx_payload)) { + radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT, + tx_pkt, tx_payload)) { result = OT_ERROR_CHANNEL_ACCESS_FAILURE; } } else { - if (radio_api->tx(radio_dev, tx_pkt, tx_payload)) { + if (radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT, + tx_pkt, tx_payload)) { result = OT_ERROR_CHANNEL_ACCESS_FAILURE; } } diff --git a/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c b/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c index 7307bd02f62..6c9dc47d68f 100644 --- a/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c +++ b/tests/net/ieee802154/l2/src/ieee802154_fake_driver.c @@ -60,6 +60,7 @@ static inline void insert_frag(struct net_pkt *pkt, struct net_buf *frag) } static int fake_tx(struct device *dev, + enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag) {