mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 05:16:47 +08:00
Merged in merlin17/nuttx/ieee802154 (pull request #358)
wireless/ieee802154: Completes basic receive functionality Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
@@ -121,6 +121,10 @@ struct mrf24j40_radio_s
|
|||||||
struct ieee802154_radio_s radio; /* The public device instance */
|
struct ieee802154_radio_s radio; /* The public device instance */
|
||||||
FAR struct ieee802154_radiocb_s *radiocb; /* Registered callbacks */
|
FAR struct ieee802154_radiocb_s *radiocb; /* Registered callbacks */
|
||||||
|
|
||||||
|
/* MAC Attributes */
|
||||||
|
|
||||||
|
bool rxonidle : 1;
|
||||||
|
|
||||||
/* Low-level MCU-specific support */
|
/* Low-level MCU-specific support */
|
||||||
|
|
||||||
FAR const struct mrf24j40_lower_s *lower;
|
FAR const struct mrf24j40_lower_s *lower;
|
||||||
@@ -186,40 +190,41 @@ static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
|
|||||||
FAR struct iob_s *frame, uint32_t fifo_addr);
|
FAR struct iob_s *frame, uint32_t fifo_addr);
|
||||||
|
|
||||||
|
|
||||||
static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev,
|
||||||
uint8_t chan);
|
uint8_t chan);
|
||||||
static int mrf24j40_getchannel(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_getchannel(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR uint8_t *chan);
|
FAR uint8_t *chan);
|
||||||
static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev,
|
||||||
uint16_t panid);
|
uint16_t panid);
|
||||||
static int mrf24j40_getpanid(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_getpanid(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR uint16_t *panid);
|
FAR uint16_t *panid);
|
||||||
static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev,
|
||||||
uint16_t saddr);
|
uint16_t saddr);
|
||||||
static int mrf24j40_getsaddr(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_getsaddr(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR uint16_t *saddr);
|
FAR uint16_t *saddr);
|
||||||
static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR const uint8_t *eaddr);
|
FAR const uint8_t *eaddr);
|
||||||
static int mrf24j40_geteaddr(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_geteaddr(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR uint8_t *eaddr);
|
FAR uint8_t *eaddr);
|
||||||
static int mrf24j40_setpromisc(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_setpromisc(FAR struct mrf24j40_radio_s *dev,
|
||||||
bool promisc);
|
bool promisc);
|
||||||
static int mrf24j40_getpromisc(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_getpromisc(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR bool *promisc);
|
FAR bool *promisc);
|
||||||
static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev,
|
||||||
uint8_t mode);
|
uint8_t mode);
|
||||||
static int mrf24j40_getdevmode(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_getdevmode(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR uint8_t *mode);
|
FAR uint8_t *mode);
|
||||||
static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev,
|
||||||
int32_t txpwr);
|
int32_t txpwr);
|
||||||
static int mrf24j40_gettxpower(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_gettxpower(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR int32_t *txpwr);
|
FAR int32_t *txpwr);
|
||||||
static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR struct ieee802154_cca_s *cca);
|
FAR struct ieee802154_cca_s *cca);
|
||||||
static int mrf24j40_getcca(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_getcca(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR struct ieee802154_cca_s *cca);
|
FAR struct ieee802154_cca_s *cca);
|
||||||
static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *radio,
|
static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev,
|
||||||
FAR uint8_t *energy);
|
FAR uint8_t *energy);
|
||||||
|
static int mrf24j40_rxenable(FAR struct mrf24j40_radio_s *dev, bool enable);
|
||||||
|
|
||||||
/* Driver operations */
|
/* Driver operations */
|
||||||
|
|
||||||
@@ -392,6 +397,12 @@ static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio,
|
|||||||
ret = IEEE802154_STATUS_SUCCESS;
|
ret = IEEE802154_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IEEE802154_PIB_MAC_RX_ON_WHEN_IDLE:
|
||||||
|
{
|
||||||
|
dev->rxonidle = attr_value->mac.rxonidle;
|
||||||
|
mrf24j40_rxenable(dev, dev->rxonidle);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
|
ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
|
||||||
}
|
}
|
||||||
@@ -1470,9 +1481,8 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable)
|
static int mrf24j40_rxenable(FAR struct mrf24j40_radio_s *dev, bool enable)
|
||||||
{
|
{
|
||||||
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
|
|
||||||
uint8_t reg;
|
uint8_t reg;
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
@@ -1567,11 +1577,14 @@ done:
|
|||||||
|
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0);
|
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0);
|
||||||
|
|
||||||
/* Enable rx int */
|
/* Only enable RX interrupt if we are to be listening when IDLE */
|
||||||
|
|
||||||
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
|
if (dev->rxonidle)
|
||||||
reg &= ~MRF24J40_INTCON_RXIE;
|
{
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
|
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
|
||||||
|
reg &= ~MRF24J40_INTCON_RXIE;
|
||||||
|
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -81,5 +81,12 @@ struct mac802154dev_txframe_s
|
|||||||
uint16_t length;
|
uint16_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mac802154dev_rxframe_s
|
||||||
|
{
|
||||||
|
struct ieee802154_data_ind_s meta;
|
||||||
|
uint8_t payload[IEEE802154_MAX_MAC_PAYLOAD_SIZE];
|
||||||
|
uint16_t length;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_WIRELESS_IEEE802154 */
|
#endif /* CONFIG_WIRELESS_IEEE802154 */
|
||||||
#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_IOCTL_H */
|
#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_IOCTL_H */
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ union ieee802154_macattr_u
|
|||||||
bool promisc_mode;
|
bool promisc_mode;
|
||||||
bool rng_support;
|
bool rng_support;
|
||||||
bool resp_wait_time;
|
bool resp_wait_time;
|
||||||
bool rx_when_idle;
|
bool rxonidle;
|
||||||
bool sec_enabled;
|
bool sec_enabled;
|
||||||
bool timestamp_support;
|
bool timestamp_support;
|
||||||
|
|
||||||
@@ -1492,6 +1492,72 @@ int mac802154dev_register(MACHANDLE mac, int minor);
|
|||||||
|
|
||||||
int mac802154netdev_register(MACHANDLE mac);
|
int mac802154netdev_register(MACHANDLE mac);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ieee802154_indpool_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function initializes the meta-data allocator. This function must
|
||||||
|
* be called early in the initialization sequence before any radios
|
||||||
|
* begin operation.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void ieee802154_indpool_initialize(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ieee802154_ind_allocate
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The ieee802154_ind_allocate function will get a free meta-data
|
||||||
|
* structure for use by the IEEE 802.15.4 MAC.
|
||||||
|
*
|
||||||
|
* Interrupt handling logic will first attempt to allocate from the
|
||||||
|
* g_indfree list. If that list is empty, it will attempt to allocate
|
||||||
|
* from its reserve, g_indfree_irq. If that list is empty, then the
|
||||||
|
* allocation fails (NULL is returned).
|
||||||
|
*
|
||||||
|
* Non-interrupt handler logic will attempt to allocate from g_indfree
|
||||||
|
* list. If that the list is empty, then the meta-data structure will be
|
||||||
|
* allocated from the dynamic memory pool.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* A reference to the allocated msg structure. All user fields in this
|
||||||
|
* structure have been zeroed. On a failure to allocate, NULL is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct ieee802154_data_ind_s *ieee802154_ind_allocate(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ieee802154_ind_free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The ieee802154_ind_free function will return a meta-data structure to
|
||||||
|
* the free pool of messages if it was a pre-allocated meta-data
|
||||||
|
* structure. If the meta-data structure was allocated dynamically it will
|
||||||
|
* be deallocated.
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* ind - meta-data structure to free
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void ieee802154_ind_free(FAR struct ieee802154_data_ind_s *ind);
|
||||||
|
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ static FAR struct mac802154_txframe_s *
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mac802154_push_rxframe
|
* Name: mac802154_push_dataind
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Push a data indication onto the list to be processed
|
* Push a data indication onto the list to be processed
|
||||||
@@ -814,6 +814,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
FAR struct iob_s *frame;
|
FAR struct iob_s *frame;
|
||||||
uint16_t *frame_ctrl;
|
uint16_t *frame_ctrl;
|
||||||
bool panid_comp;
|
bool panid_comp;
|
||||||
|
uint8_t ftype;
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
@@ -839,7 +840,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
|
|
||||||
/* Get a local copy of the frame to make it easier to access */
|
/* Get a local copy of the frame to make it easier to access */
|
||||||
|
|
||||||
frame = iob->frame;
|
frame = ind->frame;
|
||||||
|
|
||||||
/* Set a local pointer to the frame control then move the offset past
|
/* Set a local pointer to the frame control then move the offset past
|
||||||
* the frame control field
|
* the frame control field
|
||||||
@@ -852,16 +853,16 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
* this isn't a data frame
|
* this isn't a data frame
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ind->src.mode = (frame_ctrl & IEEE802154_FRAMECTRL_SADDR) >>
|
ind->src.mode = (*frame_ctrl & IEEE802154_FRAMECTRL_SADDR) >>
|
||||||
IEEE802154_FRAMECTRL_SHIFT_SADDR;
|
IEEE802154_FRAMECTRL_SHIFT_SADDR;
|
||||||
|
|
||||||
ind->dest.mode = (frame_ctrl & IEEE802154_FRAMECTRL_DADDR) >>
|
ind->dest.mode = (*frame_ctrl & IEEE802154_FRAMECTRL_DADDR) >>
|
||||||
IEEE802154_FRAMECTRL_SHIFT_DADDR;
|
IEEE802154_FRAMECTRL_SHIFT_DADDR;
|
||||||
|
|
||||||
panid_comp = (frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP) >>
|
panid_comp = (*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP) >>
|
||||||
IEEE802154_FRAMECTRL_SHIFT_PANIDCOMP;
|
IEEE802154_FRAMECTRL_SHIFT_PANIDCOMP;
|
||||||
|
|
||||||
ind->dsn = iob->frame->io_data[frame->io_offset++];
|
ind->dsn = frame->io_data[frame->io_offset++];
|
||||||
|
|
||||||
/* If the destination address is included */
|
/* If the destination address is included */
|
||||||
|
|
||||||
@@ -879,7 +880,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
}
|
}
|
||||||
else if (ind->dest.mode == IEEE802154_ADDRMODE_EXTENDED)
|
else if (ind->dest.mode == IEEE802154_ADDRMODE_EXTENDED)
|
||||||
{
|
{
|
||||||
memcpy(&ind->dest.eaddr[0], frame->io_data[frame->io_offset],
|
memcpy(&ind->dest.eaddr[0], &frame->io_data[frame->io_offset],
|
||||||
IEEE802154_EADDR_LEN);
|
IEEE802154_EADDR_LEN);
|
||||||
frame->io_offset += 8;
|
frame->io_offset += 8;
|
||||||
}
|
}
|
||||||
@@ -913,13 +914,16 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
}
|
}
|
||||||
else if (ind->src.mode == IEEE802154_ADDRMODE_EXTENDED)
|
else if (ind->src.mode == IEEE802154_ADDRMODE_EXTENDED)
|
||||||
{
|
{
|
||||||
memcpy(&ind->src.eaddr[0], frame->io_data[frame->io_offset],
|
memcpy(&ind->src.eaddr[0], &frame->io_data[frame->io_offset],
|
||||||
IEEE802154_EADDR_LEN);
|
IEEE802154_EADDR_LEN);
|
||||||
frame->io_offset += 8;
|
frame->io_offset += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftype = (*frame_ctrl & IEEE802154_FRAMECTRL_FTYPE) >>
|
||||||
|
IEEE802154_FRAMECTRL_SHIFT_FTYPE;
|
||||||
|
|
||||||
if (frame_ctrl & IEEE802154_FRAMECTRL_FTYPE == IEEE802154_FRAME_DATA)
|
if (ftype == IEEE802154_FRAME_DATA)
|
||||||
{
|
{
|
||||||
/* If there is a registered MCPS callback receiver registered, send
|
/* If there is a registered MCPS callback receiver registered, send
|
||||||
* the frame, otherwise, throw it out.
|
* the frame, otherwise, throw it out.
|
||||||
@@ -929,7 +933,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
{
|
{
|
||||||
mcps_notify.dataind = ind;
|
mcps_notify.dataind = ind;
|
||||||
priv->cb->mcps_notify(priv->cb, IEEE802154_NOTIFY_IND_DATA,
|
priv->cb->mcps_notify(priv->cb, IEEE802154_NOTIFY_IND_DATA,
|
||||||
mcps_notify);
|
&mcps_notify);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -938,11 +942,11 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
|||||||
ieee802154_ind_free(ind);
|
ieee802154_ind_free(ind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (frame_ctrl & IEEE802154_FRAMECTRL_FTYPE == IEEE802154_FRAME_COMMAND)
|
else if (ftype == IEEE802154_FRAME_COMMAND)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (frame_ctrl & IEEE802154_FRAMECTRL_FTYPE == IEEE802154_FRAME_BEACON)
|
else if (ftype == IEEE802154_FRAME_BEACON)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1023,6 +1027,10 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
|
|||||||
|
|
||||||
radiodev->ops->bind(radiodev, &mac->radiocb.cb);
|
radiodev->ops->bind(radiodev, &mac->radiocb.cb);
|
||||||
|
|
||||||
|
/* Initialize our data indication pool */
|
||||||
|
|
||||||
|
ieee802154_indpool_initialize();
|
||||||
|
|
||||||
return (MACHANDLE)mac;
|
return (MACHANDLE)mac;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1360,7 +1368,7 @@ int mac802154_req_data(MACHANDLE mac,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ((meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE) ||
|
if ((meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE) ||
|
||||||
(*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP))
|
(!(*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP)))
|
||||||
{
|
{
|
||||||
memcpy(&frame->io_data[mhr_len], &priv->addr.panid, 2);
|
memcpy(&frame->io_data[mhr_len], &priv->addr.panid, 2);
|
||||||
mhr_len += 2;
|
mhr_len += 2;
|
||||||
|
|||||||
@@ -336,70 +336,6 @@ int mac802154_resp_associate(MACHANDLE mac,
|
|||||||
int mac802154_resp_orphan(MACHANDLE mac,
|
int mac802154_resp_orphan(MACHANDLE mac,
|
||||||
FAR struct ieee802154_orphan_resp_s *resp);
|
FAR struct ieee802154_orphan_resp_s *resp);
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: ieee802154_indpool_initialize
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* This function initializes the meta-data allocator. This function must
|
|
||||||
* be called early in the initialization sequence before any radios
|
|
||||||
* begin operation.
|
|
||||||
*
|
|
||||||
* Inputs:
|
|
||||||
* None
|
|
||||||
*
|
|
||||||
* Return Value:
|
|
||||||
* None
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void ieee802154_indpool_initialize(void);
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: ieee802154_ind_allocate
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* The ieee802154_ind_allocate function will get a free meta-data
|
|
||||||
* structure for use by the IEEE 802.15.4 MAC.
|
|
||||||
*
|
|
||||||
* Interrupt handling logic will first attempt to allocate from the
|
|
||||||
* g_indfree list. If that list is empty, it will attempt to allocate
|
|
||||||
* from its reserve, g_indfree_irq. If that list is empty, then the
|
|
||||||
* allocation fails (NULL is returned).
|
|
||||||
*
|
|
||||||
* Non-interrupt handler logic will attempt to allocate from g_indfree
|
|
||||||
* list. If that the list is empty, then the meta-data structure will be
|
|
||||||
* allocated from the dynamic memory pool.
|
|
||||||
*
|
|
||||||
* Inputs:
|
|
||||||
* None
|
|
||||||
*
|
|
||||||
* Return Value:
|
|
||||||
* A reference to the allocated msg structure. All user fields in this
|
|
||||||
* structure have been zeroed. On a failure to allocate, NULL is
|
|
||||||
* returned.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
FAR struct ieee802154_data_ind_s *ieee802154_ind_allocate(void);
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: ieee802154_ind_free
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* The ieee802154_ind_free function will return a meta-data structure to
|
|
||||||
* the free pool of messages if it was a pre-allocated meta-data
|
|
||||||
* structure. If the meta-data structure was allocated dynamically it will
|
|
||||||
* be deallocated.
|
|
||||||
*
|
|
||||||
* Inputs:
|
|
||||||
* ind - meta-data structure to free
|
|
||||||
*
|
|
||||||
* Return Value:
|
|
||||||
* None
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void ieee802154_ind_free(FAR struct ieee802154_data_ind_s *ind);
|
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ struct mac802154_chardevice_s
|
|||||||
struct mac802154dev_callback_s md_cb; /* Callback information */
|
struct mac802154dev_callback_s md_cb; /* Callback information */
|
||||||
sem_t md_exclsem; /* Exclusive device access */
|
sem_t md_exclsem; /* Exclusive device access */
|
||||||
|
|
||||||
|
bool readpending; /* Is there a read using the semaphore? */
|
||||||
|
sem_t readsem; /* Signaling semaphore for waiting read */
|
||||||
|
|
||||||
/* The following is a singly linked list of open references to the
|
/* The following is a singly linked list of open references to the
|
||||||
* MAC device.
|
* MAC device.
|
||||||
*/
|
*/
|
||||||
@@ -115,6 +118,11 @@ struct mac802154_chardevice_s
|
|||||||
FAR struct mac802154dev_open_s *md_open;
|
FAR struct mac802154dev_open_s *md_open;
|
||||||
FAR struct mac802154dev_dwait_s *md_dwait;
|
FAR struct mac802154dev_dwait_s *md_dwait;
|
||||||
|
|
||||||
|
/* Hold a list of transactions as a "readahead" buffer */
|
||||||
|
|
||||||
|
FAR struct ieee802154_data_ind_s *dataind_head;
|
||||||
|
FAR struct ieee802154_data_ind_s *dataind_tail;
|
||||||
|
|
||||||
#ifndef CONFIG_DISABLE_SIGNALS
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
/* MCPS Service notification information */
|
/* MCPS Service notification information */
|
||||||
|
|
||||||
@@ -137,6 +145,12 @@ struct mac802154_chardevice_s
|
|||||||
static inline int mac802154dev_takesem(sem_t *sem);
|
static inline int mac802154dev_takesem(sem_t *sem);
|
||||||
#define mac802154dev_givesem(s) sem_post(s);
|
#define mac802154dev_givesem(s) sem_post(s);
|
||||||
|
|
||||||
|
static void mac802154dev_push_dataind(FAR struct mac802154_chardevice_s *dev,
|
||||||
|
FAR struct ieee802154_data_ind_s *ind);
|
||||||
|
static FAR struct ieee802154_data_ind_s *
|
||||||
|
mac802154dev_pop_dataind(FAR struct mac802154_chardevice_s *dev);
|
||||||
|
|
||||||
|
|
||||||
static void mac802154dev_mlme_notify(FAR const struct ieee802154_maccb_s *maccb,
|
static void mac802154dev_mlme_notify(FAR const struct ieee802154_maccb_s *maccb,
|
||||||
enum ieee802154_macnotify_e notif,
|
enum ieee802154_macnotify_e notif,
|
||||||
FAR const union ieee802154_mlme_notify_u *arg);
|
FAR const union ieee802154_mlme_notify_u *arg);
|
||||||
@@ -158,6 +172,8 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd,
|
|||||||
|
|
||||||
static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev,
|
static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev,
|
||||||
FAR const struct ieee802154_data_conf_s *conf);
|
FAR const struct ieee802154_data_conf_s *conf);
|
||||||
|
static void mac802154dev_ind_data(FAR struct mac802154_chardevice_s *dev,
|
||||||
|
FAR struct ieee802154_data_ind_s *ind);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@@ -207,6 +223,79 @@ static inline int mac802154dev_takesem(sem_t *sem)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mac802154dev_push_dataind
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Push a data indication onto the list to be processed
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void mac802154dev_push_dataind(FAR struct mac802154_chardevice_s *dev,
|
||||||
|
FAR struct ieee802154_data_ind_s *ind)
|
||||||
|
{
|
||||||
|
/* Ensure the forward link is NULL */
|
||||||
|
|
||||||
|
ind->flink = NULL;
|
||||||
|
|
||||||
|
/* If the tail is not empty, make the frame pointed to by the tail,
|
||||||
|
* point to the new data indication */
|
||||||
|
|
||||||
|
if (dev->dataind_tail != NULL)
|
||||||
|
{
|
||||||
|
dev->dataind_tail->flink = ind;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point the tail at the new frame */
|
||||||
|
|
||||||
|
dev->dataind_tail = ind;
|
||||||
|
|
||||||
|
/* If the head is NULL, we need to point it at the data indication since there
|
||||||
|
* is only one indication in the list at this point */
|
||||||
|
|
||||||
|
if (dev->dataind_head == NULL)
|
||||||
|
{
|
||||||
|
dev->dataind_head = ind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mac802154dev_pop_dataind
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Pop a data indication from the list
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static FAR struct ieee802154_data_ind_s *
|
||||||
|
mac802154dev_pop_dataind(FAR struct mac802154_chardevice_s *dev)
|
||||||
|
{
|
||||||
|
FAR struct ieee802154_data_ind_s *ind;
|
||||||
|
|
||||||
|
if (dev->dataind_head == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the data indication from the head of the list */
|
||||||
|
|
||||||
|
ind = dev->dataind_head;
|
||||||
|
ind->flink = NULL;
|
||||||
|
|
||||||
|
/* Move the head pointer to the next data indication */
|
||||||
|
|
||||||
|
dev->dataind_head = ind->flink;
|
||||||
|
|
||||||
|
/* If the head is now NULL, the list is empty, so clear the tail too */
|
||||||
|
|
||||||
|
if (dev->dataind_head == NULL)
|
||||||
|
{
|
||||||
|
dev->dataind_tail = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ind;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mac802154dev_open
|
* Name: mac802154dev_open
|
||||||
*
|
*
|
||||||
@@ -368,6 +457,8 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
{
|
{
|
||||||
FAR struct inode *inode;
|
FAR struct inode *inode;
|
||||||
FAR struct mac802154_chardevice_s *dev;
|
FAR struct mac802154_chardevice_s *dev;
|
||||||
|
FAR struct mac802154dev_rxframe_s *rx;
|
||||||
|
FAR struct ieee802154_data_ind_s *ind;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
DEBUGASSERT(filep && filep->f_inode);
|
DEBUGASSERT(filep && filep->f_inode);
|
||||||
@@ -375,20 +466,94 @@ 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;
|
||||||
|
|
||||||
/* Get exclusive access to the driver structure */
|
/* Check to make sure the buffer is the right size for the struct */
|
||||||
|
|
||||||
ret = mac802154dev_takesem(&dev->md_exclsem);
|
if (len != sizeof(struct mac802154dev_rxframe_s))
|
||||||
if (ret < 0)
|
|
||||||
{
|
{
|
||||||
wlerr("ERROR: mac802154dev_takesem failed: %d\n", ret);
|
wlerr("ERROR: buffer isn't a mac802154dev_rxframe_s: %lu\n",
|
||||||
return ret;
|
(unsigned long)len);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Add code to read a packet and return it */
|
DEBUGASSERT(buffer != NULL);
|
||||||
ret = -ENOTSUP;
|
rx = (FAR struct mac802154dev_rxframe_s *)buffer;
|
||||||
|
|
||||||
mac802154dev_givesem(&dev->md_exclsem);
|
while (1)
|
||||||
return ret;
|
{
|
||||||
|
/* Get exclusive access to the driver structure */
|
||||||
|
|
||||||
|
ret = mac802154dev_takesem(&dev->md_exclsem);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
wlerr("ERROR: mac802154dev_takesem failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try popping a data indication off the list */
|
||||||
|
|
||||||
|
ind = mac802154dev_pop_dataind(dev);
|
||||||
|
|
||||||
|
/* If the indication is not null, we can exit the loop and copy the data */
|
||||||
|
|
||||||
|
if (ind != NULL)
|
||||||
|
{
|
||||||
|
mac802154dev_givesem(&dev->md_exclsem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is a non-blocking call, or if there is another read operation
|
||||||
|
* already pending, don't block. This driver returns EAGAIN even when
|
||||||
|
* configured as non-blocking if another read operation is already pending
|
||||||
|
* This situation should be rare. It will only occur when there are 2 calls
|
||||||
|
* to read from separate threads and there was no data in the rx list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((filep->f_oflags & O_NONBLOCK) || dev->readpending)
|
||||||
|
{
|
||||||
|
mac802154dev_givesem(&dev->md_exclsem);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->readpending = true;
|
||||||
|
mac802154dev_givesem(&dev->md_exclsem);
|
||||||
|
|
||||||
|
/* Wait to be signaled when a frame is added to the list */
|
||||||
|
|
||||||
|
if (sem_wait(&dev->readsem) < 0)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(errno == EINTR);
|
||||||
|
/* Need to get exclusive access again to change the pending bool */
|
||||||
|
|
||||||
|
ret = mac802154dev_takesem(&dev->md_exclsem);
|
||||||
|
dev->readpending = false;
|
||||||
|
mac802154dev_givesem(&dev->md_exclsem);
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the loop wrap back around, we will then pop a indication and this
|
||||||
|
* time, it should have a data indication
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
rx->length = (ind->frame->io_len - ind->frame->io_offset);
|
||||||
|
|
||||||
|
/* Copy the data from the IOB to the user supplied struct */
|
||||||
|
|
||||||
|
memcpy(&rx->payload[0], &ind->frame->io_data[ind->frame->io_offset],
|
||||||
|
rx->length);
|
||||||
|
|
||||||
|
memcpy(&rx->meta, ind, sizeof(struct ieee802154_data_ind_s));
|
||||||
|
|
||||||
|
/* Zero out the forward link and IOB reference */
|
||||||
|
|
||||||
|
rx->meta.flink = NULL;
|
||||||
|
rx->meta.frame = NULL;
|
||||||
|
|
||||||
|
/* Deallocate the data indication */
|
||||||
|
|
||||||
|
ieee802154_ind_free(ind);
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -649,6 +814,11 @@ static void mac802154dev_mcps_notify(FAR const struct ieee802154_maccb_s *maccb,
|
|||||||
mac802154dev_conf_data(dev, &arg->dataconf);
|
mac802154dev_conf_data(dev, &arg->dataconf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IEEE802154_NOTIFY_IND_DATA:
|
||||||
|
{
|
||||||
|
mac802154dev_ind_data(dev, arg->dataind);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -717,6 +887,48 @@ static void mac802154dev_conf_data(FAR struct mac802154_chardevice_s *dev,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mac802154dev_ind_data(FAR struct mac802154_chardevice_s *dev,
|
||||||
|
FAR struct ieee802154_data_ind_s *ind)
|
||||||
|
{
|
||||||
|
/* Get exclusive access to the driver structure. We don't care about any
|
||||||
|
* signals so if we see one, just go back to trying to get access again */
|
||||||
|
|
||||||
|
while (mac802154dev_takesem(&dev->md_exclsem) != 0);
|
||||||
|
|
||||||
|
/* Push the indication onto the list */
|
||||||
|
|
||||||
|
mac802154dev_push_dataind(dev, ind);
|
||||||
|
|
||||||
|
/* Check if there is a read waiting for data */
|
||||||
|
|
||||||
|
if (dev->readpending)
|
||||||
|
{
|
||||||
|
/* Wake the thread waiting for the data transmission */
|
||||||
|
|
||||||
|
dev->readpending = false;
|
||||||
|
sem_post(&dev->readsem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the driver */
|
||||||
|
|
||||||
|
mac802154dev_givesem(&dev->md_exclsem);
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_SIGNALS
|
||||||
|
/* Send a signal to the registered application */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_PASS_STRUCTS
|
||||||
|
/* Copy the status as the signal data to be optionally used by app */
|
||||||
|
|
||||||
|
union sigval value;
|
||||||
|
value.sival_int = IEEE802154_STATUS_SUCCESS;
|
||||||
|
(void)sigqueue(dev->md_mcps_pid, dev->md_mcps_notify.mn_signo, value);
|
||||||
|
#else
|
||||||
|
(void)sigqueue(dev->md_mcps_pid, dev->md_mcps_notify.mn_signo,
|
||||||
|
value.sival_ptr);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -758,6 +970,10 @@ int mac802154dev_register(MACHANDLE mac, int minor)
|
|||||||
dev->md_mac = mac;
|
dev->md_mac = mac;
|
||||||
sem_init(&dev->md_exclsem, 0, 1); /* Allow the device to be opened once
|
sem_init(&dev->md_exclsem, 0, 1); /* Allow the device to be opened once
|
||||||
* before blocking */
|
* before blocking */
|
||||||
|
|
||||||
|
sem_init(&dev->readsem, 0, 0);
|
||||||
|
sem_setprotocol(&dev->readsem, SEM_PRIO_NONE);
|
||||||
|
dev->readpending = false;
|
||||||
|
|
||||||
/* Initialize the MAC callbacks */
|
/* Initialize the MAC callbacks */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user