2017-09-15 16:37:55 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* drivers/wireless/xbee/drivers/xbee_mac.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 Verge Inc. All rights reserved.
|
|
|
|
* Author: Anthony Merlino <anthony@vergeaero.com>
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
|
|
|
* used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <nuttx/mm/iob.h>
|
|
|
|
|
|
|
|
#include "xbee.h"
|
|
|
|
#include "xbee_mac.h"
|
|
|
|
|
|
|
|
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
|
|
|
|
#include <nuttx/wireless/ieee802154/xbee.h>
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#define XBEE_ASSOC_POLLDELAY 100
|
2018-06-13 05:21:45 +02:00
|
|
|
|
2018-11-01 20:05:04 +01:00
|
|
|
#define XBEE_RESPONSE_TIMEOUT MSEC2TICK(200)
|
2017-09-15 16:37:55 +02:00
|
|
|
|
2019-01-15 21:19:09 +01:00
|
|
|
#ifdef CONFIG_XBEE_LOCKUP_WORKAROUND
|
|
|
|
#define XBEE_LOCKUP_SENDATTEMPTS 20
|
|
|
|
#endif
|
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Private Types
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Function Prototypes
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-08-09 20:29:35 +02:00
|
|
|
static void xbee_assoctimer(wdparm_t arg);
|
2017-09-15 16:37:55 +02:00
|
|
|
static void xbee_assocworker(FAR void *arg);
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_assoctimer
|
|
|
|
*
|
|
|
|
* Description:
|
2020-08-06 19:41:45 +02:00
|
|
|
* This function is used to schedule * an associatioin indication poll.
|
|
|
|
* When association first gets triggered, a watchdog timer is started. This
|
|
|
|
* function is called when it expires. The watchdog timer is scheduled
|
|
|
|
* again until the association is either successful or fails.
|
2017-09-15 16:37:55 +02:00
|
|
|
*
|
2018-03-13 16:52:27 +01:00
|
|
|
* Input Parameters:
|
2020-08-09 20:29:35 +02:00
|
|
|
* arg - The argument
|
2017-09-15 16:37:55 +02:00
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-08-09 20:29:35 +02:00
|
|
|
static void xbee_assoctimer(wdparm_t arg)
|
2017-09-15 16:37:55 +02:00
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)arg;
|
|
|
|
int ret;
|
|
|
|
|
2020-02-23 09:50:23 +01:00
|
|
|
/* In complex environments, we cannot do SPI transfers from the timeout
|
2017-09-15 16:37:55 +02:00
|
|
|
* handler because semaphores are probably used to lock the SPI bus. In
|
|
|
|
* this case, we will defer processing to the worker thread. This is also
|
|
|
|
* much kinder in the use of system resources and is, therefore, probably
|
|
|
|
* a good thing to do in any event.
|
|
|
|
*/
|
|
|
|
|
|
|
|
DEBUGASSERT(priv && work_available(&priv->assocwork));
|
|
|
|
|
|
|
|
/* Notice that poll watchdog is not active so further poll timeouts can
|
|
|
|
* occur until we restart the poll timeout watchdog.
|
|
|
|
*/
|
|
|
|
|
2020-08-06 19:41:45 +02:00
|
|
|
ret = work_queue(HPWORK, &priv->assocwork,
|
|
|
|
xbee_assocworker, (FAR void *)priv, 0);
|
2020-01-02 17:49:34 +01:00
|
|
|
UNUSED(ret);
|
2017-09-15 16:37:55 +02:00
|
|
|
DEBUGASSERT(ret == OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_assocworker
|
|
|
|
*
|
|
|
|
* Description:
|
2020-08-06 19:41:45 +02:00
|
|
|
* Poll the device for the assosciation status. This function is indirectly
|
|
|
|
* scheduled rom xbee_req_associate in order to poll the device for
|
|
|
|
* association progress.
|
2017-09-15 16:37:55 +02:00
|
|
|
*
|
2018-03-13 16:52:27 +01:00
|
|
|
* Input Parameters:
|
2017-09-15 16:37:55 +02:00
|
|
|
* arg - The reference to the driver structure (cast to void*)
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void xbee_assocworker(FAR void *arg)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)arg;
|
|
|
|
|
2019-01-10 22:31:57 +01:00
|
|
|
if (priv->associating)
|
|
|
|
{
|
|
|
|
xbee_send_atquery(priv, "AI");
|
2017-09-15 16:37:55 +02:00
|
|
|
|
2020-08-04 12:31:31 +02:00
|
|
|
wd_start(&priv->assocwd, XBEE_ASSOC_POLLDELAY,
|
2020-08-09 20:29:35 +02:00
|
|
|
xbee_assoctimer, (wdparm_t)arg);
|
2019-01-10 22:31:57 +01:00
|
|
|
}
|
2017-09-15 16:37:55 +02:00
|
|
|
}
|
|
|
|
|
2018-04-19 06:08:13 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_reqdata_timeout
|
|
|
|
*
|
|
|
|
* Description:
|
2020-08-06 19:41:45 +02:00
|
|
|
* This function runs when a send request has timed out waiting for a
|
|
|
|
* response from the XBee module. This really should never happen, but if
|
|
|
|
* it does, handle it gracefully by retrying the query. Although I still
|
|
|
|
* think this should not happen, it does seem to happen. The XBee seemingly
|
|
|
|
* randomly drops the request and never sends a response.
|
2018-04-19 06:08:13 +02:00
|
|
|
*
|
|
|
|
* Parameters:
|
2020-08-09 20:29:35 +02:00
|
|
|
* arg - The argument
|
2018-04-19 06:08:13 +02:00
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-08-09 20:29:35 +02:00
|
|
|
static void xbee_reqdata_timeout(wdparm_t arg)
|
2018-04-19 06:08:13 +02:00
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)arg;
|
|
|
|
|
|
|
|
DEBUGASSERT(priv != NULL);
|
|
|
|
|
|
|
|
wlwarn("Send timeout\n");
|
|
|
|
|
|
|
|
/* Wake the pending reqdata thread so it can retry */
|
|
|
|
|
|
|
|
nxsem_post(&priv->txdone_sem);
|
|
|
|
}
|
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_bind
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Bind the MAC callback table to the XBee driver.
|
|
|
|
*
|
2018-03-13 16:52:27 +01:00
|
|
|
* Input Parameters:
|
2017-09-15 16:37:55 +02:00
|
|
|
* xbee - Reference to the XBee driver structure
|
|
|
|
* cb - MAC callback operations
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* OK on success; Negated errno on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int xbee_bind(XBEEHANDLE xbee, FAR struct xbee_maccb_s *cb)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
FAR struct xbee_maccb_s *next;
|
|
|
|
FAR struct xbee_maccb_s *prev;
|
|
|
|
|
|
|
|
/* Add the MAC client callback structure to the list of MAC callbacks in
|
|
|
|
* priority order.
|
|
|
|
*
|
|
|
|
* Search the list to find the location to insert the new instance.
|
|
|
|
* The list is maintained in descending priority order.
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (prev = NULL, next = priv->cb;
|
|
|
|
(next != NULL && cb->prio <= next->prio);
|
|
|
|
prev = next, next = next->flink);
|
|
|
|
|
|
|
|
/* Add the instance to the spot found in the list. Check if the instance
|
|
|
|
* goes at the head of the list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (prev == NULL)
|
|
|
|
{
|
|
|
|
cb->flink = priv->cb; /* May be NULL */
|
|
|
|
priv->cb = cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No.. the instance goes between prev and next */
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cb->flink = next; /* May be NULL */
|
|
|
|
prev->flink = cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Keep track of the number of clients requesting notification */
|
|
|
|
|
|
|
|
if (cb->notify != NULL)
|
|
|
|
{
|
|
|
|
priv->nclients++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_get_mhrlen
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Calculate the MAC header length given the frame meta-data. For the XBee,
|
|
|
|
* we use the header to store the entire API frame for the TX request. The
|
2020-08-06 19:41:45 +02:00
|
|
|
* size we need is fixed based on the address mode we are using as it
|
|
|
|
* changes which API frame we need to issue.
|
2017-09-15 16:37:55 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-08-06 19:41:45 +02:00
|
|
|
int xbee_get_mhrlen(XBEEHANDLE xbee,
|
|
|
|
FAR const struct ieee802154_frame_meta_s *meta)
|
2017-09-15 16:37:55 +02:00
|
|
|
{
|
|
|
|
int ret = 9; /* Smallest possible header size */
|
|
|
|
|
|
|
|
/* We assume that the XBee is configured with application header on but
|
|
|
|
* encryption not on.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ret += 2;
|
|
|
|
|
|
|
|
if (meta->srcmode == IEEE802154_ADDRMODE_EXTENDED)
|
|
|
|
{
|
|
|
|
ret += 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (meta->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
|
|
|
|
{
|
|
|
|
ret += 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_req_data
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* The MCPS-DATA.request primitive requests the transfer of a data SPDU
|
|
|
|
* (i.e., MSDU) from a local SSCS entity to a single peer SSCS entity.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int xbee_req_data(XBEEHANDLE xbee,
|
|
|
|
FAR const struct ieee802154_frame_meta_s *meta,
|
|
|
|
FAR struct iob_s *frame)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
int index;
|
|
|
|
uint16_t apiframelen;
|
|
|
|
uint8_t frametype;
|
2017-09-15 21:41:24 +02:00
|
|
|
#ifdef CONFIG_DEBUG_ASSERTIONS
|
2017-09-15 16:37:55 +02:00
|
|
|
int prevoffs = frame->io_offset;
|
2017-09-15 21:41:24 +02:00
|
|
|
#endif
|
2019-01-15 21:19:09 +01:00
|
|
|
#ifdef CONFIG_XBEE_LOCKUP_WORKAROUND
|
|
|
|
int retries = XBEE_LOCKUP_SENDATTEMPTS;
|
|
|
|
#endif
|
2017-09-15 16:37:55 +02:00
|
|
|
|
2017-11-01 21:15:21 +01:00
|
|
|
/* Support one pending transmit at a time */
|
|
|
|
|
|
|
|
while (nxsem_wait(&priv->tx_sem) < 0);
|
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
/* Figure out how much room we need to place the API frame header */
|
|
|
|
|
|
|
|
if (meta->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
|
|
|
|
{
|
|
|
|
DEBUGASSERT(frame->io_offset >= 14);
|
|
|
|
frame->io_offset -= 14;
|
|
|
|
frametype = XBEE_APIFRAME_TXREQ_EADDR;
|
|
|
|
}
|
|
|
|
else if (meta->destaddr.mode == IEEE802154_ADDRMODE_SHORT)
|
|
|
|
{
|
|
|
|
DEBUGASSERT(frame->io_offset >= 8);
|
|
|
|
frame->io_offset -= 8;
|
|
|
|
frametype = XBEE_APIFRAME_TXREQ_SADDR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
index = frame->io_offset;
|
|
|
|
apiframelen = (frame->io_len - frame->io_offset - 3);
|
|
|
|
|
|
|
|
frame->io_data[index++] = XBEE_STARTBYTE;
|
2019-12-05 18:49:12 +01:00
|
|
|
frame->io_data[index++] = ((apiframelen >> 8) & 0xff);
|
|
|
|
frame->io_data[index++] = (apiframelen & 0xff);
|
2017-09-15 16:37:55 +02:00
|
|
|
frame->io_data[index++] = frametype;
|
|
|
|
frame->io_data[index++] = xbee_next_frameid(priv);
|
|
|
|
|
|
|
|
if (meta->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
|
|
|
|
{
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[7];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[6];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[5];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[4];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[3];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[2];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[1];
|
|
|
|
frame->io_data[index++] = meta->destaddr.eaddr[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
frame->io_data[index++] = meta->destaddr.saddr[1];
|
|
|
|
frame->io_data[index++] = meta->destaddr.saddr[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
frame->io_data[index++] = 0; /* Options byte. Currently we do not support anything here */
|
|
|
|
|
|
|
|
DEBUGASSERT(index == prevoffs);
|
|
|
|
|
|
|
|
/* Increment io_len by 1 to account for checksum */
|
|
|
|
|
|
|
|
frame->io_len++;
|
|
|
|
xbee_insert_checksum(&frame->io_data[frame->io_offset],
|
|
|
|
(frame->io_len - frame->io_offset));
|
|
|
|
|
2018-04-19 06:08:13 +02:00
|
|
|
priv->txdone = false;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* Setup a timeout in case the XBee never responds with a tx status */
|
|
|
|
|
2020-08-04 12:31:31 +02:00
|
|
|
wd_start(&priv->reqdata_wd, XBEE_RESPONSE_TIMEOUT,
|
2020-08-09 20:29:35 +02:00
|
|
|
xbee_reqdata_timeout, (wdparm_t)priv);
|
2017-09-15 16:37:55 +02:00
|
|
|
|
2018-04-19 06:08:13 +02:00
|
|
|
/* Send the frame */
|
2017-11-01 21:15:21 +01:00
|
|
|
|
2018-04-19 06:08:13 +02:00
|
|
|
xbee_send_apiframe(priv, &frame->io_data[frame->io_offset],
|
|
|
|
(frame->io_len - frame->io_offset));
|
|
|
|
|
2020-08-06 19:41:45 +02:00
|
|
|
/* Wait for a transmit status to be received. Does not necessarily mean
|
|
|
|
* success
|
|
|
|
*/
|
2018-04-19 06:08:13 +02:00
|
|
|
|
|
|
|
while (nxsem_wait(&priv->txdone_sem) < 0);
|
2018-12-21 18:17:29 +01:00
|
|
|
|
2020-08-06 19:41:45 +02:00
|
|
|
/* If the transmit timeout has occurred, and there are no IOBs
|
|
|
|
* available, we may be blocking the context needed to free the IOBs.
|
|
|
|
* We cannot receive the Tx status because it requires an IOB.
|
|
|
|
* Therefore, if we have hit the timeout, and there are no IOBs, let's
|
|
|
|
* move on assuming the transmit was a success
|
2018-12-21 18:17:29 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
if (!priv->txdone && iob_navail(false) <= 0)
|
|
|
|
{
|
|
|
|
wlwarn("Couldn't confirm TX. No IOBs\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-01-15 21:19:09 +01:00
|
|
|
#ifdef CONFIG_XBEE_LOCKUP_WORKAROUND
|
|
|
|
if (--retries == 0 && !priv->txdone)
|
|
|
|
{
|
|
|
|
wlerr("XBee not responding. Resetting.\n");
|
|
|
|
priv->lower->reset(priv->lower);
|
|
|
|
retries = XBEE_LOCKUP_SENDATTEMPTS;
|
|
|
|
}
|
|
|
|
#endif
|
2018-04-19 06:08:13 +02:00
|
|
|
}
|
|
|
|
while (!priv->txdone);
|
2017-11-01 21:15:21 +01:00
|
|
|
|
|
|
|
nxsem_post(&priv->tx_sem);
|
2019-08-20 00:50:21 +02:00
|
|
|
iob_free(frame, IOBUSER_WIRELESS_RAD802154);
|
2017-09-15 16:37:55 +02:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_req_get
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* The MLME-GET.request primitive requests information about a given PIB
|
|
|
|
* attribute.
|
|
|
|
*
|
|
|
|
* NOTE: The standard specifies that the attribute value should be returned
|
2020-02-23 09:50:23 +01:00
|
|
|
* via the asynchronous MLME-GET.confirm primitive. However, in our
|
2020-08-06 19:41:45 +02:00
|
|
|
* implementation, we synchronously return the value immediately.Therefore,
|
|
|
|
* we merge the functionality of the MLME-GET.request and MLME-GET.confirm
|
2017-09-15 16:37:55 +02:00
|
|
|
* primitives together.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int xbee_req_get(XBEEHANDLE xbee, enum ieee802154_attr_e attr,
|
|
|
|
FAR union ieee802154_attr_u *attrval)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
int ret = IEEE802154_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
switch (attr)
|
|
|
|
{
|
|
|
|
case IEEE802154_ATTR_MAC_PANID:
|
|
|
|
{
|
|
|
|
xbee_query_panid(priv);
|
|
|
|
IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE802154_ATTR_MAC_SADDR:
|
|
|
|
{
|
|
|
|
xbee_query_saddr(priv);
|
|
|
|
IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE802154_ATTR_MAC_EADDR:
|
|
|
|
{
|
|
|
|
xbee_query_eaddr(priv);
|
|
|
|
IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE802154_ATTR_MAC_COORD_SADDR:
|
|
|
|
{
|
2019-12-05 18:49:12 +01:00
|
|
|
IEEE802154_SADDRCOPY(attrval->mac.coordsaddr,
|
|
|
|
priv->pandesc.coordaddr.saddr);
|
2017-09-15 16:37:55 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE802154_ATTR_MAC_COORD_EADDR:
|
|
|
|
{
|
2019-12-05 18:49:12 +01:00
|
|
|
IEEE802154_EADDRCOPY(attrval->mac.coordeaddr,
|
|
|
|
priv->pandesc.coordaddr.eaddr);
|
2017-09-15 16:37:55 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE802154_ATTR_MAC_DEVMODE:
|
|
|
|
{
|
|
|
|
attrval->mac.devmode = priv->devmode;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEEE802154_ATTR_PHY_CHAN:
|
|
|
|
{
|
|
|
|
xbee_query_chan(priv);
|
|
|
|
attrval->phy.chan = priv->chan;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2018-11-01 20:05:04 +01:00
|
|
|
case IEEE802154_ATTR_PHY_TX_POWER:
|
|
|
|
{
|
2020-08-06 19:41:45 +02:00
|
|
|
/* TODO: Convert pwrlvl and boost mode settings to int32_t dbm.
|
|
|
|
* This depends on whether device is XBee or XBee Pro to do this
|
|
|
|
* look-up.
|
2018-11-01 20:05:04 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
xbee_query_powerlevel(priv);
|
|
|
|
attrval->phy.txpwr = priv->pwrlvl;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2019-08-10 20:05:07 +02:00
|
|
|
case IEEE802154_ATTR_PHY_FCS_LEN:
|
|
|
|
{
|
|
|
|
attrval->phy.fcslen = 2;
|
|
|
|
ret = IEEE802154_STATUS_SUCCESS;
|
|
|
|
}
|
2019-08-10 20:29:58 +02:00
|
|
|
break;
|
2019-08-10 20:05:07 +02:00
|
|
|
|
|
|
|
case IEEE802154_ATTR_PHY_REGDUMP:
|
2017-09-15 16:37:55 +02:00
|
|
|
{
|
|
|
|
xbee_regdump(priv);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
wlwarn("Unsupported attribute\n");
|
|
|
|
ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_req_set
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* The MLME-SET.request primitive attempts to write the given value to the
|
|
|
|
* indicated MAC PIB attribute.
|
|
|
|
*
|
|
|
|
* NOTE: The standard specifies that confirmation should be indicated via
|
2020-08-06 19:41:45 +02:00
|
|
|
* the asynchronous MLME-SET.confirm primitive. However, in our
|
|
|
|
* implementation we synchronously return the status from the request.
|
|
|
|
* Therefore, we do merge the functionality of the MLME-SET.request and
|
|
|
|
* MLME-SET.confirm primitives together.
|
2017-09-15 16:37:55 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int xbee_req_set(XBEEHANDLE xbee, enum ieee802154_attr_e attr,
|
|
|
|
FAR const union ieee802154_attr_u *attrval)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
int ret = IEEE802154_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
switch (attr)
|
|
|
|
{
|
|
|
|
case IEEE802154_ATTR_MAC_PANID:
|
|
|
|
{
|
|
|
|
xbee_set_panid(priv, attrval->mac.panid);
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_MAC_EADDR:
|
|
|
|
{
|
|
|
|
ret = IEEE802154_STATUS_DENIED;
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_MAC_SADDR:
|
|
|
|
{
|
|
|
|
xbee_set_saddr(priv, attrval->mac.saddr);
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_PHY_CHAN:
|
|
|
|
{
|
|
|
|
xbee_set_chan(priv, attrval->phy.chan);
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT:
|
|
|
|
{
|
|
|
|
if (attrval->mac.assocpermit)
|
|
|
|
{
|
2020-08-06 19:41:45 +02:00
|
|
|
xbee_set_coordassocflags(priv,
|
|
|
|
XBEE_COORDASSOCFLAGS_ALLOWASSOC);
|
2017-09-15 16:37:55 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xbee_set_coordassocflags(priv, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2018-11-01 20:05:04 +01:00
|
|
|
case IEEE802154_ATTR_PHY_TX_POWER:
|
|
|
|
{
|
2020-08-06 19:41:45 +02:00
|
|
|
/* TODO: Convert int32_t dbm input to closest PM/PL settings. Need
|
|
|
|
* to know whether device is XBee or XBee Pro to do this look-up.
|
2018-11-01 20:05:04 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
xbee_set_powerlevel(priv, attrval->phy.txpwr);
|
|
|
|
}
|
|
|
|
break;
|
2017-09-15 16:37:55 +02:00
|
|
|
#if 0
|
|
|
|
case IEEE802154_ATTR_MAC_COORD_SADDR:
|
|
|
|
{
|
|
|
|
xbee_set_coordsaddr(priv, attrval->mac.coordsaddr);
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_MAC_COORD_EADDR:
|
|
|
|
{
|
|
|
|
xbee_set_coordeaddr(priv, attrval->mac.coordeaddr);
|
|
|
|
}
|
|
|
|
break;
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME:
|
|
|
|
{
|
|
|
|
priv->resp_waittime = attrval->mac.resp_waittime;
|
|
|
|
}
|
2019-12-05 18:49:12 +01:00
|
|
|
break;
|
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
case IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE:
|
|
|
|
{
|
|
|
|
xbee_setrxonidle(priv, attrval->mac.rxonidle);
|
|
|
|
}
|
2019-12-05 18:49:12 +01:00
|
|
|
break;
|
2017-09-15 16:37:55 +02:00
|
|
|
#endif
|
2019-12-05 18:49:12 +01:00
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
wlwarn("Unsupported attribute\n");
|
|
|
|
ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_req_start
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* The MLME-START.request primitive makes a request for the device to start
|
|
|
|
* acting as a coordinator. The XBee modules do not support beacon-enabled
|
|
|
|
* networking!
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int xbee_req_start(XBEEHANDLE xbee, FAR struct ieee802154_start_req_s *req)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
|
|
|
|
if (req->beaconorder != 15)
|
|
|
|
{
|
|
|
|
wlwarn("xbee: beacon-enabled networks not supported\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
xbee_set_panid(priv, req->panid);
|
|
|
|
xbee_set_chan(priv, req->chan);
|
|
|
|
|
|
|
|
xbee_enable_coord(priv, true);
|
|
|
|
xbee_set_sleepperiod(priv, 0);
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_req_associate
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* The MLME-ASSOCIATE.request primitive allows a device to request an
|
|
|
|
* association with a coordinator.
|
|
|
|
*
|
|
|
|
* On receipt of the MLME-ASSOCIATE.request primitive, the MLME of an
|
|
|
|
* unassociated device first updates the appropriate PHY and MAC PIB
|
|
|
|
* attributes, as described in 5.1.3.1, and then generates an association
|
|
|
|
* request command, as defined in 5.3.1 [1] pg.80
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-08-06 19:41:45 +02:00
|
|
|
int xbee_req_associate(XBEEHANDLE xbee,
|
|
|
|
FAR struct ieee802154_assoc_req_s *req)
|
2017-09-15 16:37:55 +02:00
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
|
|
|
|
if (req->coordaddr.mode == IEEE802154_ADDRMODE_NONE)
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
xbee_enable_coord(priv, false);
|
|
|
|
|
|
|
|
xbee_set_panid(priv, req->coordaddr.panid);
|
|
|
|
xbee_set_chan(priv, req->chan);
|
|
|
|
|
|
|
|
xbee_set_epassocflags(priv, XBEE_EPASSOCFLAGS_AUTOASSOC);
|
|
|
|
|
2019-01-10 22:31:57 +01:00
|
|
|
priv->associating = true;
|
|
|
|
|
2017-09-15 16:37:55 +02:00
|
|
|
/* In order to track the association status, we must poll the device for
|
|
|
|
* an update.
|
|
|
|
*/
|
|
|
|
|
2020-08-04 12:31:31 +02:00
|
|
|
return wd_start(&priv->assocwd, XBEE_ASSOC_POLLDELAY,
|
2020-08-09 20:29:35 +02:00
|
|
|
xbee_assoctimer, (wdparm_t)priv);
|
2017-09-15 16:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: xbee_req_reset
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* The MLME-RESET.request primitive allows the next higher layer to request
|
|
|
|
* that the MLME performs a reset operation.
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
2020-08-06 19:41:45 +02:00
|
|
|
* xbee - Handle to the XBee instance
|
|
|
|
* resetattr - Whether or not to reset the MAC PIB attributes to defaults
|
2017-09-15 16:37:55 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
int xbee_req_reset(XBEEHANDLE xbee, bool resetattr)
|
|
|
|
{
|
|
|
|
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
|
|
|
|
|
|
|
|
/* Reset the XBee radio */
|
|
|
|
|
|
|
|
priv->lower->reset(priv->lower);
|
|
|
|
|
|
|
|
if (resetattr)
|
|
|
|
{
|
|
|
|
xbee_set_panid(priv, IEEE802154_PANID_UNSPEC);
|
|
|
|
xbee_set_saddr(priv, IEEE802154_SADDR_UNSPEC);
|
|
|
|
xbee_enable_coord(priv, false);
|
|
|
|
xbee_set_epassocflags(priv, 0);
|
|
|
|
xbee_set_coordassocflags(priv, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|