wireless/ieee802154: Changes transmit data path to use IOBs and exposes function for getting size of MAC header
This commit is contained in:
parent
ea44684f0c
commit
f02d98d15e
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user