wireless/ieee802154: Changes transmit data path to use IOBs and exposes function for getting size of MAC header

This commit is contained in:
Anthony Merlino 2017-05-02 09:12:56 -04:00
parent ea44684f0c
commit f02d98d15e
7 changed files with 262 additions and 215 deletions

View File

@ -138,9 +138,10 @@ struct mrf24j40_radio_s
/* Buffer Allocations */ /* Buffer Allocations */
struct mrf24j40_txdesc_s csma_desc; 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 void mrf24j40_dopoll_gts(FAR void *arg);
static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, 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, 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, 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 */ /* 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, static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *radio, int cmd,
unsigned long arg); unsigned long arg);
static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio); static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio);
static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio);
FAR uint8_t *buf, uint16_t buf_len); 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 * 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; FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg;
int len = 0; int len = 0;
/* Need to get exlusive access to the device so that we can use the copy /* Get exclusive access to the driver */
* buffer.
*/
while (sem_wait(&dev->exclsem) != 0) { } 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 */ /* need to somehow allow for a handle to be passed */
len = 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]); &dev->csma_frame);
if (len > 0) if (len > 0)
{ {
/* Now the txdesc is in use */ /* 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 */ /* 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 gts = 0;
int len = 0; int len = 0;
/* Need to get exclusive access to the device so that we can use the copy /* Get exclusive access to the driver */
* buffer.
*/
while (sem_wait(&dev->exclsem) != 0) { } while (sem_wait(&dev->exclsem) != 0) { }
@ -432,7 +427,7 @@ static void mrf24j40_dopoll_gts(FAR void *arg)
if (!dev->gts_desc[gts].busy) if (!dev->gts_desc[gts].busy)
{ {
len = 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]); &dev->gts_frame[0]);
if (len > 0) if (len > 0)
{ {
/* Now the txdesc is in use */ /* 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 */ /* 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; 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 * 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, 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; uint8_t reg;
int ret; int ret;
@ -1397,7 +1346,7 @@ static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev,
/* Setup the FIFO */ /* 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 /* If the frame control field contains
* an acknowledgment request, set the TXNACKREQ bit. * 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; reg = MRF24J40_TXNCON_TXNTRIG;
if (buf[0] & IEEE802154_FRAMECTRL_ACKREQ) if (frame->io_data[0] & IEEE802154_FRAMECTRL_ACKREQ)
{ {
reg |= MRF24J40_TXNCON_TXNACKREQ; 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, 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; 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, static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
FAR uint8_t *buf, uint16_t buf_len, FAR struct iob_s *frame, uint32_t fifo_addr)
uint32_t fifo_addr)
{ {
int ret; int ret;
int hlen = 3; /* Include frame control and seq number */ 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 */ /* Analyze frame control to compute header length */
frame_ctrl = buf[0]; frame_ctrl = frame->io_data[0];
frame_ctrl |= (buf[1] << 8); frame_ctrl |= (frame->io_data[1] << 8);
if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR)== IEEE802154_ADDRMODE_SHORT) 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 */ /* Frame length */
mrf24j40_setreg(dev->spi, fifo_addr++, buf_len); mrf24j40_setreg(dev->spi, fifo_addr++, frame->io_len);
/* Frame data */ /* 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; return ret;
@ -1525,6 +1473,10 @@ static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev)
dev->csma_desc.busy = 0; dev->csma_desc.busy = 0;
/* Free the IOB */
iob_free(dev->csma_frame);
mrf24j40_dopoll_csma(dev); 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; dev->gts_desc[gts].busy = 0;
/* Free the IOB */
iob_free(dev->gts_frame[gts]);
mrf24j40_dopoll_gts(dev); mrf24j40_dopoll_gts(dev);
} }

View File

@ -72,6 +72,11 @@ struct mac802154dev_notify_s
uint8_t mn_signo; /* Signal number to use in the notification */ 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 /* CONFIG_WIRELESS_IEEE802154 */
#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_IOCTL_H */ #endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_IOCTL_H */

View File

@ -474,20 +474,12 @@ enum ieee802154_scantype_e
IEEE802154_SCANTYPE_ORPHAN IEEE802154_SCANTYPE_ORPHAN
}; };
/* Primitive Semantics *******************************************************/ struct ieee802154_frame_meta_s
/*****************************************************************************
* Primitive: MCPS-DATA.request
*
* Description:
* Requests the transfer of data to another device.
*
*****************************************************************************/
struct ieee802154_data_req_s
{ {
enum ieee802154_addr_mode_e src_addr_mode; /* Source Address Mode */ enum ieee802154_addr_mode_e src_addr_mode; /* Source Address Mode */
struct ieee802154_addr_s dest_addr; /* Destination Address */ 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) /* Number of bytes contained in the MAC Service Data Unit (MSDU)
* to be transmitted by the MAC sublayer enitity * to be transmitted by the MAC sublayer enitity
@ -498,7 +490,6 @@ struct ieee802154_data_req_s
uint16_t msdu_length; uint16_t msdu_length;
uint8_t msdu_handle; /* Handle assoc. with MSDU */
struct struct
{ {
uint8_t ack_tx : 1; /* Acknowledge TX? */ uint8_t ack_tx : 1; /* Acknowledge TX? */
@ -530,18 +521,23 @@ struct ieee802154_data_req_s
#endif #endif
enum ieee802154_ranging_e ranging; 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) \ /* Primitive Semantics *******************************************************/
(sizeof(struct ieee802154_data_req_s) \
- IEEE802154_MAX_MAC_PAYLOAD_SIZE + (n)) /*****************************************************************************
* 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 * Primitive: MCPS-DATA.confirm

View File

@ -195,13 +195,15 @@ struct ieee802154_rxdesc_s
struct ieee802154_radiocb_s struct ieee802154_radiocb_s
{ {
CODE int (*poll_csma) (FAR const 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); FAR struct ieee802154_txdesc_s *tx_desc,
FAR struct iob_s **frame);
CODE int (*poll_gts) (FAR const 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); FAR struct ieee802154_txdesc_s *tx_desc,
FAR struct iob_s **frame);
CODE void (*txdone) (FAR const struct ieee802154_radiocb_s *radiocb, CODE void (*txdone) (FAR const struct ieee802154_radiocb_s *radiocb,
FAR const struct ieee802154_txdesc_s *tx_desc); FAR const struct ieee802154_txdesc_s *tx_desc);
CODE void (*rxframe) (FAR const struct ieee802154_radiocb_s *radiocb, 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); FAR struct iob_s *frame);
}; };

View File

@ -86,15 +86,8 @@ struct mac802154_trans_s
/* Supports a singly linked list */ /* Supports a singly linked list */
FAR struct mac802154_trans_s *flink; FAR struct mac802154_trans_s *flink;
FAR struct iob_s *frame;
uint8_t msdu_handle; 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; 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, static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc, 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, static int mac802154_poll_gts(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc, 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, static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb,
FAR const struct ieee802154_txdesc_s *tx_desc); FAR const struct ieee802154_txdesc_s *tx_desc);
static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, 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 iob_s *frame);
/**************************************************************************** /****************************************************************************
* Private Data * 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 * 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, static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc, 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 *cb =
(FAR struct mac802154_radiocb_s *)radiocb; (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) if (trans != NULL)
{ {
/* Setup the transmit descriptor */ /* Setup the transmit descriptor */
tx_desc->handle = trans->msdu_handle; tx_desc->handle = trans->msdu_handle;
/* Copy the frame into the buffer */ *frame = trans->frame;
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. /* Now that we've passed off the data, notify the waiting thread.
* NOTE: The transaction was allocated on the waiting thread's stack so * NOTE: The transaction was allocated on the waiting thread's stack so
* it will be automatically deallocated when that thread awakens and * it will be automatically deallocated when that thread awakens and
* returns. * returns. */
*/
sem_post(&trans->sem); sem_post(&trans->sem);
return (trans->mhr_len + trans->d_len); return (trans->frame->io_len);
} }
return 0; 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, static int mac802154_poll_gts(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_txdesc_s *tx_desc, 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 *cb =
(FAR struct mac802154_radiocb_s *)radiocb; (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, 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 iob_s *frame)
{ {
FAR struct mac802154_radiocb_s *cb = FAR struct mac802154_radiocb_s *cb =
@ -844,6 +835,82 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg)
* MAC Interface Operations * 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 * 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 *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
FAR struct mac802154_trans_s trans; 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; 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 frame_ctrl = (uint16_t *)&req->frame->io_data[0];
* the best case.
*/
if (req->msdu_length > IEEE802154_MAX_MAC_PAYLOAD_SIZE)
{
return -EINVAL;
}
/* Ensure we start with a clear frame control field */ /* Ensure we start with a clear frame control field */
mhr.u.frame_control = 0; *frame_ctrl = 0;
/* Set the frame type to Data */ /* Set the frame type to Data */
mhr.u.frame_control |= IEEE802154_FRAME_DATA << *frame_ctrl |= IEEE802154_FRAME_DATA << IEEE802154_FRAMECTRL_SHIFT_FTYPE;
IEEE802154_FRAMECTRL_SHIFT_FTYPE;
/* If the msduLength is greater than aMaxMACSafePayloadSize, the MAC /* If the msduLength is greater than aMaxMACSafePayloadSize, the MAC
* sublayer will set the Frame Version to one. [1] pg. 118. * 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 /* If the TXOptions parameter specifies that an acknowledged transmission
* is required, the AR field will be set appropriately, as described in * is required, the AR field will be set appropriately, as described in
* 5.1.6.4 [1] pg. 118. * 5.1.6.4 [1] pg. 118.
*/ */
mhr.u.frame_control |= (req->msdu_flags.ack_tx << *frame_ctrl |= (meta->msdu_flags.ack_tx << IEEE802154_FRAMECTRL_SHIFT_ACKREQ);
IEEE802154_FRAMECTRL_SHIFT_ACKREQ);
/* If the destination address is present, copy the PAN ID and one of the /* 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); memcpy(&req->frame->io_data[mhr_len], &meta->dest_addr.panid, 2);
mhr.length += 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); memcpy(&req->frame->io_data[mhr_len], &meta->dest_addr.saddr, 2);
mhr.length += 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); memcpy(&req->frame->io_data[mhr_len], &meta->dest_addr.eaddr, 8);
mhr.length += 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 << *frame_ctrl |= (meta->dest_addr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR);
IEEE802154_FRAMECTRL_SHIFT_DADDR);
/* From this point on, we need exclusive access to the privmac struct */ /* 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. * [1] pg. 41.
*/ */
if (req->src_addr_mode != IEEE802154_ADDRMODE_NONE && if (meta->src_addr_mode != IEEE802154_ADDRMODE_NONE &&
req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE)
{ {
/* If the PAN identifiers are identical, the PAN ID Compression field /* If the PAN identifiers are identical, the PAN ID Compression field
* shall be set to one, and the source PAN identifier shall be omitted * shall be set to one, and the source PAN identifier shall be omitted
* from the transmitted frame. [1] pg. 41. * 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 /* If the destination address is not included, or if PAN ID Compression
* is off, we need to include the Source PAN ID. * is off, we need to include the Source PAN ID.
*/ */
if ((req->dest_addr.mode == IEEE802154_ADDRMODE_NONE) || if ((meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE) ||
(mhr.u.frame_control & IEEE802154_FRAMECTRL_PANIDCOMP)) (*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP))
{ {
memcpy(&mhr.u.data[mhr.length], &priv->addr.panid, 2); memcpy(&req->frame->io_data[mhr_len], &priv->addr.panid, 2);
mhr.length += 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); memcpy(&req->frame->io_data[mhr_len], &priv->addr.saddr, 2);
mhr.length += 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); memcpy(&req->frame->io_data[mhr_len], &priv->addr.eaddr, 8);
mhr.length += 8; mhr_len += 8;
} }
} }
/* Set the source addr mode inside the frame control field */ /* Set the source addr mode inside the frame control field */
mhr.u.frame_control |= (req->src_addr_mode << *frame_ctrl |= (meta->src_addr_mode << IEEE802154_FRAMECTRL_SHIFT_SADDR);
IEEE802154_FRAMECTRL_SHIFT_SADDR);
/* Each time a data or a MAC command frame is generated, the MAC sublayer /* 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 * 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. * 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 /* The MAC header we just created must never have exceeded where the app
* sure we actually have enough room in the PSDU. * 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 > DEBUGASSERT(mhr_len == req->frame->io_offset);
IEEE802154_MAX_PHY_PACKET_SIZE)
{
return -E2BIG;
}
trans.mhr_buf = &mhr.u.data[0]; req->frame->io_offset = 0; /* Set the offset to 0 to include the header */
trans.mhr_len = mhr.length;
trans.d_buf = &req->msdu[0]; /* Setup our transaction */
trans.d_len = req->msdu_length;
trans.msdu_handle = req->msdu_handle;
trans.msdu_handle = meta->msdu_handle;
trans.frame = req->frame;
sem_init(&trans.sem, 0, 1); sem_init(&trans.sem, 0, 1);
/* If the TxOptions parameter specifies that a GTS transmission is required, /* 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. * [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 /* TODO: Support GTS transmission. This should just change where we link
* the transaction. Instead of going in the CSMA transaction list, it * 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] * 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 /* If the TxOptions parameter specifies that an indirect transmission
* is required and if the device receiving this primitive is not a * 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] * 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 */ /* Link the transaction into the indirect_trans list */
priv->indirect_tail->flink = &trans;
priv->indirect_tail = &trans;
} }
else else
{ {
/* Override the setting since it wasn't valid */ /* 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 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 */ /* 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; return OK;
} }
/**************************************************************************** /****************************************************************************
* Name: mac802154_req_purge * Name: mac802154_req_purge
* *

View File

@ -97,6 +97,17 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg);
* MAC Interface Operations * 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 * Name: mac802154_req_data
* *

View File

@ -50,6 +50,8 @@
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/drivers/iob.h>
#include <nuttx/wireless/ieee802154/ieee802154_ioctl.h> #include <nuttx/wireless/ieee802154/ieee802154_ioctl.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h> #include <nuttx/wireless/ieee802154/ieee802154_mac.h>
@ -373,17 +375,6 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer,
DEBUGASSERT(inode->i_private); DEBUGASSERT(inode->i_private);
dev = (FAR struct mac802154_chardevice_s *)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 */ /* Get exclusive access to the driver structure */
ret = mac802154dev_takesem(&dev->md_exclsem); 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 inode *inode;
FAR struct mac802154_chardevice_s *dev; 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; struct mac802154dev_dwait_s dwait;
int ret; int ret;
@ -422,20 +415,44 @@ static ssize_t mac802154dev_write(FAR struct file *filep,
DEBUGASSERT(inode->i_private); DEBUGASSERT(inode->i_private);
dev = (FAR struct mac802154_chardevice_s *)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 /* Check if the struct is write */
* packet. */
if ((len < SIZEOF_IEEE802154_DATA_REQ_S(1)) || if (len != sizeof(struct mac802154dev_txframe_s))
(len > SIZEOF_IEEE802154_DATA_REQ_S(IEEE802154_MAX_MAC_PAYLOAD_SIZE)))
{ {
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); (unsigned long)len);
return -EINVAL; return -EINVAL;
} }
DEBUGASSERT(buffer != NULL); 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 /* 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 * 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 */ /* Setup the wait struct */
dwait.mw_handle = req->msdu_handle; dwait.mw_handle = tx->meta->msdu_handle;
/* Link the wait struct */ /* Link the wait struct */
dwait.mw_flink = dev->md_dwait; dwait.mw_flink = dev->md_dwait;
dev->md_dwait = &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); mac802154dev_givesem(&dev->md_exclsem);
} }
req.meta = tx->meta;
req.frame = iob;
/* Pass the request to the MAC layer */ /* 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) if (ret < 0)
{ {