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 */
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);
}

View File

@ -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 */

View File

@ -474,21 +474,13 @@ 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
* Note: This could be a uint8_t but if anyone ever wants to use
@ -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

View File

@ -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);
};

View File

@ -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,38 +927,37 @@ 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;
/* Start off assuming there is only the frame_control field in the MHR */
/* Check the required frame size */
mhr.length = 2;
if (req->frame->io_len > IEEE802154_MAX_PHY_PACKET_SIZE)
{
return -E2BIG;
}
/* Do a preliminary check to make sure the MSDU isn't too long for even
* the best case.
*/
/* Cast the first two bytes of the IOB to a uint16_t frame control field */
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
@ -899,34 +965,32 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req)
* 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
*

View File

@ -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
*

View File

@ -50,6 +50,8 @@
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <nuttx/drivers/iob.h>
#include <nuttx/wireless/ieee802154/ieee802154_ioctl.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);
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)
{