From f02d98d15e27f5c28dfd48ffbc88623f6129433c Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Tue, 2 May 2017 09:12:56 -0400 Subject: [PATCH] wireless/ieee802154: Changes transmit data path to use IOBs and exposes function for getting size of MAC header --- drivers/wireless/ieee802154/mrf24j40.c | 108 +++----- .../wireless/ieee802154/ieee802154_ioctl.h | 5 + .../wireless/ieee802154/ieee802154_mac.h | 40 ++- .../wireless/ieee802154/ieee802154_radio.h | 8 +- wireless/ieee802154/mac802154.c | 242 +++++++++++------- wireless/ieee802154/mac802154.h | 11 + wireless/ieee802154/mac802154_device.c | 63 +++-- 7 files changed, 262 insertions(+), 215 deletions(-) diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index 6b602b739d..f883b55054 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -138,9 +138,10 @@ struct mrf24j40_radio_s /* Buffer Allocations */ struct mrf24j40_txdesc_s csma_desc; - struct mrf24j40_txdesc_s gts_desc[MRF24J40_GTS_SLOTS]; + FAR struct iob_s *csma_frame; - uint8_t tx_buf[IEEE802154_MAX_PHY_PACKET_SIZE]; + struct mrf24j40_txdesc_s gts_desc[MRF24J40_GTS_SLOTS]; + FAR struct iob_s *gts_frame[MRF24J40_GTS_SLOTS]; }; /**************************************************************************** @@ -174,11 +175,11 @@ static void mrf24j40_dopoll_csma(FAR void *arg); static void mrf24j40_dopoll_gts(FAR void *arg); static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *buf, uint16_t buf_len); + FAR struct iob_s *frame); static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, - FAR uint8_t *buf, uint16_t buf_len); + FAR struct iob_s *frame); static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *buf, uint16_t buf_len, uint32_t fifo_addr); + FAR struct iob_s *frame, uint32_t fifo_addr); /* IOCTL helpers */ @@ -224,10 +225,8 @@ static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, 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); -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); -static int mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio); +static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio); +static int mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio); /**************************************************************************** * Private Data @@ -327,9 +326,7 @@ static void mrf24j40_dopoll_csma(FAR void *arg) FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; int len = 0; - /* Need to get exlusive access to the device so that we can use the copy - * buffer. - */ + /* Get exclusive access to the driver */ while (sem_wait(&dev->exclsem) != 0) { } @@ -340,7 +337,7 @@ static void mrf24j40_dopoll_csma(FAR void *arg) /* need to somehow allow for a handle to be passed */ len = dev->radiocb->poll_csma(dev->radiocb, &dev->csma_desc.pub, - &dev->tx_buf[0]); + &dev->csma_frame); if (len > 0) { /* Now the txdesc is in use */ @@ -349,7 +346,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], len); + mrf24j40_csma_setup(dev, dev->csma_frame); } } @@ -421,9 +418,7 @@ static void mrf24j40_dopoll_gts(FAR void *arg) int gts = 0; int len = 0; - /* Need to get exclusive access to the device so that we can use the copy - * buffer. - */ + /* Get exclusive access to the driver */ while (sem_wait(&dev->exclsem) != 0) { } @@ -432,7 +427,7 @@ static void mrf24j40_dopoll_gts(FAR void *arg) if (!dev->gts_desc[gts].busy) { len = dev->radiocb->poll_gts(dev->radiocb, &dev->gts_desc[gts].pub, - &dev->tx_buf[0]); + &dev->gts_frame[0]); if (len > 0) { /* Now the txdesc is in use */ @@ -441,7 +436,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], len); + mrf24j40_gts_setup(dev, gts, dev->gts_frame[0]); } } } @@ -1327,52 +1322,6 @@ static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, return OK; } -/* Packet exchange */ - -/**************************************************************************** - * Name: mrf24j40_transmit - * - * Description: - * Send a regular packet over the air. - * - ****************************************************************************/ - -static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, - FAR uint8_t *buf, uint16_t buf_len) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - uint8_t reg; - int ret; - - mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - - /* Enable tx int */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg &= ~MRF24J40_INTCON_TXNIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - /* Setup the FIFO */ - - ret = mrf24j40_setup_fifo(dev, buf, buf_len, MRF24J40_TXNORM_FIFO); - - /* If the frame control field contains - * an acknowledgment request, set the TXNACKREQ bit. - * See IEEE 802.15.4/2003 7.2.1.1 page 112 for info. - */ - - reg = MRF24J40_TXNCON_TXNTRIG; - if (buf[0] & IEEE802154_FRAMECTRL_ACKREQ) - { - reg |= MRF24J40_TXNCON_TXNACKREQ; - } - - /* Trigger packet emission */ - - mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); - return ret; -} - /**************************************************************************** * Name: mrf24j40_csma_setup * @@ -1382,7 +1331,7 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, ****************************************************************************/ static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *buf, uint16_t buf_len) + FAR struct iob_s *frame) { uint8_t reg; int ret; @@ -1397,7 +1346,7 @@ static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, /* Setup the FIFO */ - ret = mrf24j40_setup_fifo(dev, buf, buf_len, MRF24J40_TXNORM_FIFO); + ret = mrf24j40_setup_fifo(dev, frame, MRF24J40_TXNORM_FIFO); /* If the frame control field contains * an acknowledgment request, set the TXNACKREQ bit. @@ -1405,7 +1354,7 @@ static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, */ reg = MRF24J40_TXNCON_TXNTRIG; - if (buf[0] & IEEE802154_FRAMECTRL_ACKREQ) + if (frame->io_data[0] & IEEE802154_FRAMECTRL_ACKREQ) { reg |= MRF24J40_TXNCON_TXNACKREQ; } @@ -1425,7 +1374,7 @@ static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, ****************************************************************************/ static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, - FAR uint8_t *buf, uint16_t buf_len) + FAR struct iob_s *frame) { return -ENOTTY; } @@ -1438,8 +1387,7 @@ static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, ****************************************************************************/ static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, - FAR uint8_t *buf, uint16_t buf_len, - uint32_t fifo_addr) + FAR struct iob_s *frame, uint32_t fifo_addr) { int ret; int hlen = 3; /* Include frame control and seq number */ @@ -1447,8 +1395,8 @@ static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, /* Analyze frame control to compute header length */ - frame_ctrl = buf[0]; - frame_ctrl |= (buf[1] << 8); + frame_ctrl = frame->io_data[0]; + frame_ctrl |= (frame->io_data[1] << 8); if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR)== IEEE802154_ADDRMODE_SHORT) { @@ -1479,13 +1427,13 @@ static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, /* Frame length */ - mrf24j40_setreg(dev->spi, fifo_addr++, buf_len); + mrf24j40_setreg(dev->spi, fifo_addr++, frame->io_len); /* Frame data */ - for (ret = 0; ret < buf_len; ret++) /* this sets the correct val for ret */ + for (ret = 0; ret < frame->io_len; ret++) /* this sets the correct val for ret */ { - mrf24j40_setreg(dev->spi, fifo_addr++, buf[ret]); + mrf24j40_setreg(dev->spi, fifo_addr++, frame->io_data[ret]); } return ret; @@ -1525,6 +1473,10 @@ static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev) dev->csma_desc.busy = 0; + /* Free the IOB */ + + iob_free(dev->csma_frame); + mrf24j40_dopoll_csma(dev); } @@ -1571,6 +1523,10 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, dev->gts_desc[gts].busy = 0; + /* Free the IOB */ + + iob_free(dev->gts_frame[gts]); + mrf24j40_dopoll_gts(dev); } diff --git a/include/nuttx/wireless/ieee802154/ieee802154_ioctl.h b/include/nuttx/wireless/ieee802154/ieee802154_ioctl.h index 533e2f3853..019fedd55a 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_ioctl.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_ioctl.h @@ -72,6 +72,11 @@ struct mac802154dev_notify_s uint8_t mn_signo; /* Signal number to use in the notification */ }; +struct mac802154dev_txframe_s +{ + FAR struct ieee802154_frame_meta_s *meta; + FAR uint8_t *payload; +}; #endif /* CONFIG_WIRELESS_IEEE802154 */ #endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_IOCTL_H */ diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 1a8e324ce2..422e4d88fb 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -474,20 +474,12 @@ enum ieee802154_scantype_e IEEE802154_SCANTYPE_ORPHAN }; -/* Primitive Semantics *******************************************************/ - -/***************************************************************************** - * Primitive: MCPS-DATA.request - * - * Description: - * Requests the transfer of data to another device. - * - *****************************************************************************/ - -struct ieee802154_data_req_s +struct ieee802154_frame_meta_s { enum ieee802154_addr_mode_e src_addr_mode; /* Source Address Mode */ struct ieee802154_addr_s dest_addr; /* Destination Address */ + + uint8_t msdu_handle; /* Handle assoc. with MSDU */ /* Number of bytes contained in the MAC Service Data Unit (MSDU) * to be transmitted by the MAC sublayer enitity @@ -498,7 +490,6 @@ struct ieee802154_data_req_s uint16_t msdu_length; - uint8_t msdu_handle; /* Handle assoc. with MSDU */ struct { uint8_t ack_tx : 1; /* Acknowledge TX? */ @@ -530,18 +521,23 @@ struct ieee802154_data_req_s #endif enum ieee802154_ranging_e ranging; - - /* The MAC service data unit array that is to be transmitted - * This must be at the end of the struct to allow the array - * to continue and make the struct "variable length" - */ - - uint8_t msdu[IEEE802154_MAX_MAC_PAYLOAD_SIZE]; }; -#define SIZEOF_IEEE802154_DATA_REQ_S(n) \ - (sizeof(struct ieee802154_data_req_s) \ - - IEEE802154_MAX_MAC_PAYLOAD_SIZE + (n)) +/* Primitive Semantics *******************************************************/ + +/***************************************************************************** + * Primitive: MCPS-DATA.request + * + * Description: + * Requests the transfer of data to another device. + * + *****************************************************************************/ + +struct ieee802154_data_req_s +{ + FAR struct ieee802154_frame_meta_s *meta; /* Metadata describing the req */ + FAR struct iob_s *frame; /* Frame IOB with payload */ +}; /***************************************************************************** * Primitive: MCPS-DATA.confirm diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index 54e08969d9..e976ec2075 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -195,13 +195,15 @@ struct ieee802154_rxdesc_s struct ieee802154_radiocb_s { CODE int (*poll_csma) (FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc, FAR uint8_t *buf); + FAR struct ieee802154_txdesc_s *tx_desc, + FAR struct iob_s **frame); CODE int (*poll_gts) (FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s *tx_desc, FAR uint8_t *buf); + FAR struct ieee802154_txdesc_s *tx_desc, + FAR struct iob_s **frame); CODE void (*txdone) (FAR const struct ieee802154_radiocb_s *radiocb, FAR const struct ieee802154_txdesc_s *tx_desc); CODE void (*rxframe) (FAR const struct ieee802154_radiocb_s *radiocb, - FAR const struct ieee8021254_rxdesc_s *rx_desc, + FAR const struct ieee802154_rxdesc_s *rx_desc, FAR struct iob_s *frame); }; diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index f6b5f5f455..1dbd3a65c2 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -86,15 +86,8 @@ struct mac802154_trans_s /* Supports a singly linked list */ FAR struct mac802154_trans_s *flink; - + FAR struct iob_s *frame; 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; }; @@ -291,23 +284,26 @@ static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv); 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 iob_s **frame); 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 iob_s **frame); 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 const struct ieee802154_rxdesc_s *rx_desc, FAR struct iob_s *frame); /**************************************************************************** * Private Data ****************************************************************************/ +/* Map between ieee802154_addr_mode_e enum and actual address length */ + +static const uint8_t mac802154_addr_length[4] = {0, 0, 2, 8}; /**************************************************************************** * Private Functions @@ -452,7 +448,7 @@ static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv) 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 iob_s **frame) { FAR struct mac802154_radiocb_s *cb = (FAR struct mac802154_radiocb_s *)radiocb; @@ -475,24 +471,19 @@ static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb, if (trans != NULL) { - /* 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); + *frame = trans->frame; /* 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. - */ + * returns. */ sem_post(&trans->sem); - return (trans->mhr_len + trans->d_len); + return (trans->frame->io_len); } return 0; @@ -511,7 +502,7 @@ static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb, 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 iob_s **frame) { FAR struct mac802154_radiocb_s *cb = (FAR struct mac802154_radiocb_s *)radiocb; @@ -643,7 +634,7 @@ static void mac802154_txdone_worker(FAR void *arg) ****************************************************************************/ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_rxdesc_s *rx_desc, + FAR const struct ieee802154_rxdesc_s *rx_desc, FAR struct iob_s *frame) { FAR struct mac802154_radiocb_s *cb = @@ -844,6 +835,82 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) * MAC Interface Operations ****************************************************************************/ +/**************************************************************************** + * Name: mac802154_get_mhrlen + * + * Description: + * Calculate the MAC header length given the frame meta-data. + * + ****************************************************************************/ + +int mac802154_get_mhrlen(MACHANDLE mac, + FAR struct ieee802154_frame_meta_s *meta) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret = 3; /* Always frame control (2 bytes) and seq. num (1 byte) */ + + /* Check to make sure both the dest address and the source address are not set + * to NONE */ + + if (meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE && + meta->src_addr_mode == IEEE802154_ADDRMODE_NONE) + { + return -EINVAL; + } + + /* The source address can only be set to NONE if the device is the PAN coord */ + + if (meta->src_addr_mode == IEEE802154_ADDRMODE_NONE && !priv->is_coord) + { + return -EINVAL; + } + + /* Add the destination address length */ + + ret += mac802154_addr_length[meta->dest_addr.mode]; + + /* Add the source address length */ + + ret += mac802154_addr_length[ meta->src_addr_mode]; + + /* If both destination and source addressing information is present, the MAC + * sublayer shall compare the destination and source PAN identifiers. + * [1] pg. 41. + */ + + if (meta->src_addr_mode != IEEE802154_ADDRMODE_NONE && + meta->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 (meta->dest_addr.panid == priv->addr.panid) + { + ret += 2; /* 2 bytes for destination PAN ID */ + return ret; + } + } + + /* If we are here, PAN ID compression is off, so include the dest and source + * PAN ID if the respective address is included + */ + + if (meta->src_addr_mode != IEEE802154_ADDRMODE_NONE) + { + ret += 2; /* 2 bytes for source PAN ID */ + } + + if (meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + { + ret += 2; /* 2 bytes for destination PAN ID */ + } + + return ret; +} + /**************************************************************************** * Name: mac802154_req_data * @@ -860,73 +927,70 @@ 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; + FAR struct ieee802154_frame_meta_s *meta = req->meta; + uint16_t *frame_ctrl; + uint8_t mhr_len = 3; /* Start assuming frame control and seq. num */ int ret; + + /* Check the required frame size */ - /* Start off assuming there is only the frame_control field in the MHR */ + if (req->frame->io_len > IEEE802154_MAX_PHY_PACKET_SIZE) + { + return -E2BIG; + } - mhr.length = 2; + /* Cast the first two bytes of the IOB to a uint16_t frame control field */ - /* 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; - } + frame_ctrl = (uint16_t *)&req->frame->io_data[0]; /* Ensure we start with a clear frame control field */ - mhr.u.frame_control = 0; + *frame_ctrl = 0; /* Set the frame type to Data */ - mhr.u.frame_control |= IEEE802154_FRAME_DATA << - IEEE802154_FRAMECTRL_SHIFT_FTYPE; + *frame_ctrl |= 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) + if (meta->msdu_length > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) { - mhr.u.frame_control |= IEEE802154_FRAMECTRL_VERSION; + *frame_ctrl |= 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); + + *frame_ctrl |= (meta->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 . + * addresses, depending on mode, into the MHR. */ - if (req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + if (meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) { - memcpy(&mhr.u.data[mhr.length], &req->dest_addr.panid, 2); - mhr.length += 2; + memcpy(&req->frame->io_data[mhr_len], &meta->dest_addr.panid, 2); + mhr_len += 2; - if (req->dest_addr.mode == IEEE802154_ADDRMODE_SHORT) + if (meta->dest_addr.mode == IEEE802154_ADDRMODE_SHORT) { - memcpy(&mhr.u.data[mhr.length], &req->dest_addr.saddr, 2); - mhr.length += 2; + memcpy(&req->frame->io_data[mhr_len], &meta->dest_addr.saddr, 2); + mhr_len += 2; } - else if (req->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + else if (meta->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) { - memcpy(&mhr.u.data[mhr.length], &req->dest_addr.eaddr, 8); - mhr.length += 8; + memcpy(&req->frame->io_data[mhr_len], &meta->dest_addr.eaddr, 8); + mhr_len += 8; } } - /* Set the destination addr mode inside the frame contorl field */ + /* Set the destination addr mode inside the frame control field */ - mhr.u.frame_control |= (req->dest_addr.mode << - IEEE802154_FRAMECTRL_SHIFT_DADDR); + *frame_ctrl |= (meta->dest_addr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); /* From this point on, we need exclusive access to the privmac struct */ @@ -942,75 +1006,70 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) * [1] pg. 41. */ - if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE && - req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + if (meta->src_addr_mode != IEEE802154_ADDRMODE_NONE && + meta->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) + if (meta->dest_addr.panid == priv->addr.panid) { - mhr.u.frame_control |= IEEE802154_FRAMECTRL_PANIDCOMP; + *frame_ctrl |= IEEE802154_FRAMECTRL_PANIDCOMP; } } - if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE) + if (meta->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)) + if ((meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE) || + (*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP)) { - memcpy(&mhr.u.data[mhr.length], &priv->addr.panid, 2); - mhr.length += 2; + memcpy(&req->frame->io_data[mhr_len], &priv->addr.panid, 2); + mhr_len += 2; } - if (req->src_addr_mode == IEEE802154_ADDRMODE_SHORT) + if (meta->src_addr_mode == IEEE802154_ADDRMODE_SHORT) { - memcpy(&mhr.u.data[mhr.length], &priv->addr.saddr, 2); - mhr.length += 2; + memcpy(&req->frame->io_data[mhr_len], &priv->addr.saddr, 2); + mhr_len += 2; } - else if (req->src_addr_mode == IEEE802154_ADDRMODE_EXTENDED) + else if (meta->src_addr_mode == IEEE802154_ADDRMODE_EXTENDED) { - memcpy(&mhr.u.data[mhr.length], &priv->addr.eaddr, 8); - mhr.length += 8; + memcpy(&req->frame->io_data[mhr_len], &priv->addr.eaddr, 8); + mhr_len += 8; } } /* Set the source addr mode inside the frame control field */ - mhr.u.frame_control |= (req->src_addr_mode << - IEEE802154_FRAMECTRL_SHIFT_SADDR); + *frame_ctrl |= (meta->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++; + req->frame->io_data[2] = 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. + /* The MAC header we just created must never have exceeded where the app + * data starts. This should never happen since the offset should have + * been set via the same logic to calculate the header length as the logic + * here that created the header */ - if (mhr.length + req->msdu_length + IEEE802154_MFR_LENGTH > - IEEE802154_MAX_PHY_PACKET_SIZE) - { - return -E2BIG; - } + DEBUGASSERT(mhr_len == req->frame->io_offset); - trans.mhr_buf = &mhr.u.data[0]; - trans.mhr_len = mhr.length; + req->frame->io_offset = 0; /* Set the offset to 0 to include the header */ - trans.d_buf = &req->msdu[0]; - trans.d_len = req->msdu_length; - - trans.msdu_handle = req->msdu_handle; + /* Setup our transaction */ + trans.msdu_handle = meta->msdu_handle; + trans.frame = req->frame; sem_init(&trans.sem, 0, 1); /* If the TxOptions parameter specifies that a GTS transmission is required, @@ -1025,7 +1084,7 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) * [1] pg. 118. */ - if (req->msdu_flags.gts_tx) + if (meta->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 @@ -1044,7 +1103,7 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) * described in 5.1.5 and 5.1.6.3. [1] */ - if (req->msdu_flags.indirect_tx) + if (meta->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 @@ -1053,24 +1112,22 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) * transmission option will be ignored. [1] */ - if (priv->is_coord && req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + if (priv->is_coord && meta->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; + meta->msdu_flags.indirect_tx = 0; } } /* If this is a direct transmission not during a GTS */ - if (!req->msdu_flags.indirect_tx) + if (!meta->msdu_flags.indirect_tx) { /* Link the transaction into the CSMA transaction list */ @@ -1092,7 +1149,6 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) return OK; } - /**************************************************************************** * Name: mac802154_req_purge * diff --git a/wireless/ieee802154/mac802154.h b/wireless/ieee802154/mac802154.h index 00235d025b..ea582e4e7a 100644 --- a/wireless/ieee802154/mac802154.h +++ b/wireless/ieee802154/mac802154.h @@ -97,6 +97,17 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg); * MAC Interface Operations ****************************************************************************/ +/**************************************************************************** + * Name: mac802154_get_mhrlen + * + * Description: + * Calculate the MAC header length given the frame meta-data. + * + ****************************************************************************/ + +int mac802154_get_mhrlen(MACHANDLE mac, + FAR struct ieee802154_frame_meta_s *meta); + /**************************************************************************** * Name: mac802154_req_data * diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index 5c31cdf140..998cca074f 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -50,6 +50,8 @@ #include #include +#include + #include #include @@ -373,17 +375,6 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer, DEBUGASSERT(inode->i_private); dev = (FAR struct mac802154_chardevice_s *)inode->i_private; - /* Check to make sure that the buffer is big enough to hold at least one - * packet. - */ - - if ((len >= SIZEOF_IEEE802154_DATA_REQ_S(1)) && - (len <= SIZEOF_IEEE802154_DATA_REQ_S(IEEE802154_MAX_MAC_PAYLOAD_SIZE))) - { - wlerr("ERROR: buffer too small: %lu\n", (unsigned long)len); - return -EINVAL; - } - /* Get exclusive access to the driver structure */ ret = mac802154dev_takesem(&dev->md_exclsem); @@ -413,7 +404,9 @@ static ssize_t mac802154dev_write(FAR struct file *filep, { FAR struct inode *inode; FAR struct mac802154_chardevice_s *dev; - FAR struct ieee802154_data_req_s *req; + FAR struct mac802154dev_txframe_s *tx; + FAR struct iob_s *iob; + struct ieee802154_data_req_s req; struct mac802154dev_dwait_s dwait; int ret; @@ -422,20 +415,44 @@ static ssize_t mac802154dev_write(FAR struct file *filep, DEBUGASSERT(inode->i_private); dev = (FAR struct mac802154_chardevice_s *)inode->i_private; - /* Check to make sure that the buffer is big enough to hold at least one - * packet. */ + /* Check if the struct is write */ - if ((len < SIZEOF_IEEE802154_DATA_REQ_S(1)) || - (len > SIZEOF_IEEE802154_DATA_REQ_S(IEEE802154_MAX_MAC_PAYLOAD_SIZE))) + if (len != sizeof(struct mac802154dev_txframe_s)) { - wlerr("ERROR: buffer isn't an ieee802154_data_req_s: %lu\n", + wlerr("ERROR: buffer isn't a mac802154dev_txframe_s: %lu\n", (unsigned long)len); return -EINVAL; } DEBUGASSERT(buffer != NULL); - req = (FAR struct ieee802154_data_req_s *)buffer; + tx = (FAR struct mac802154dev_txframe_s *)buffer; + + /* Allocate an IOB to put the frame in */ + + iob = iob_alloc(false); + DEBUGASSERT(iob != NULL); + + iob->io_flink = NULL; + iob->io_len = 0; + iob->io_offset = 0; + iob->io_pktlen = 0; + + /* Get the MAC header length */ + + ret = mac802154_get_mhrlen(dev->md_mac, tx->meta); + if (ret < 0) + { + wlerr("ERROR: TX meta-data is invalid"); + return ret; + } + + iob->io_offset = ret; + iob->io_len = iob->io_offset; + + memcpy(&iob->io_data[iob->io_offset], tx->payload, tx->meta->msdu_length); + + iob->io_len += tx->meta->msdu_length; /* If this is a blocking operation, we need to setup a wait struct so we * can unblock when the packet transmission has finished. If this is a @@ -456,21 +473,25 @@ static ssize_t mac802154dev_write(FAR struct file *filep, /* Setup the wait struct */ - dwait.mw_handle = req->msdu_handle; + dwait.mw_handle = tx->meta->msdu_handle; /* Link the wait struct */ dwait.mw_flink = dev->md_dwait; dev->md_dwait = &dwait; - sem_init(&dwait.mw_sem, 0, 1); + sem_init(&dwait.mw_sem, 0, 0); + sem_setprotocol(&dwait.mw_sem, SEM_PRIO_NONE); mac802154dev_givesem(&dev->md_exclsem); } + req.meta = tx->meta; + req.frame = iob; + /* Pass the request to the MAC layer */ - ret = mac802154_req_data(dev->md_mac, req); + ret = mac802154_req_data(dev->md_mac, &req); if (ret < 0) {