Skip to content
mac802154.c 66.7 KiB
Newer Older
/****************************************************************************
 * wireless/ieee802154/mac802154.c
 *
 *   Copyright (C) 2016 Sebastien Lorquet. All rights reserved.
 *   Copyright (C) 2017 Gregory Nutt. All rights reserved.
 *   Copyright (C) 2017 Verge Inc. All rights reserved.
 *   Author: Sebastien Lorquet <sebastien@lorquet.fr>
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *   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 <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <string.h>

#include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/mm/iob.h>
#include "mac802154_internal.h"
#include "mac802154_assoc.h"
#include "mac802154_data.h"
#include "mac802154_poll.h"
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/* Data structure pools and allocation helpers */

static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv);
static int mac802154_radiopoll(FAR const struct ieee802154_radiocb_s *radiocb,
                               bool gts, FAR struct ieee802154_txdesc_s **tx_desc);

static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb,
                             FAR struct ieee802154_txdesc_s *tx_desc);
static void mac802154_txdone_worker(FAR void *arg);

static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb,
                              FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxframe_worker(FAR void *arg);
static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
                              enum ieee802154_sfevent_e sfevent);
static void mac802154_purge_worker(FAR void *arg);
static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
                                FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
                                  FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
                                    FAR struct ieee802154_data_ind_s *ind);
static void mac802154_notify_worker(FAR void *arg);

/****************************************************************************
 ****************************************************************************/

/****************************************************************************
 *   Initializes the various queues used in the MAC layer. Called on creation
 *   of MAC.
 *
 ****************************************************************************/

static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv)
  sq_init(&priv->txdone_queue);
  sq_init(&priv->csma_queue);
  sq_init(&priv->indirect_queue);
  sq_init(&priv->dataind_queue);
  sq_init(&priv->primitive_queue);
  /* Initialize the tx descriptor allocation pool */
  for (i = 0; i < CONFIG_MAC802154_NTXDESC; i++)
      sq_addlast((FAR sq_entry_t *)&priv->txdesc_pool[i], &priv->txdesc_queue);
  nxsem_init(&priv->txdesc_sem, 0, CONFIG_MAC802154_NTXDESC);
/****************************************************************************
 * Name: mac802154_txdesc_pool
 *
 * Description:
 *   This function allocates a tx descriptor and the dependent primitive (data
 *   confirmation) from the free list. The primitive and tx descriptor must be
 *   freed seperately.
 *
 * Assumptions:
 *   priv MAC struct is locked when calling.
 *
 * Notes:
 *   If any of the semaphore waits inside this function get interrupted, the
 *   function will release the MAC layer.  If this function returns -EINTR, the
 *   calling code should NOT release the MAC semaphore.
 *
 ****************************************************************************/

int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
                           FAR struct ieee802154_txdesc_s **txdesc,
                           bool allow_interrupt)
  FAR struct ieee802154_primitive_s *primitive;
  /* Try and take a count from the semaphore.  If this succeeds, we have
   * "reserved" the structure, but still need to unlink it from the free list.
   * The MAC is already locked, so there shouldn't be any other conflicting calls
   */

  ret = nxsem_trywait(&priv->txdesc_sem);
      *txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->txdesc_queue);
    }
  else
    {
      /* Unlock MAC so that other work can be done to free a notification */


      /* Take a count from the tx desc semaphore, waiting if necessary. We
       * only return from here with an error if we are allowing interruptions
       * and we received a signal */

      ret = mac802154_takesem(&priv->txdesc_sem, allow_interrupt);
      if (ret < 0)
        {
          /* MAC is already released */

          wlwarn("WARNING: mac802154_takesem failed: %d\n", ret);
          return -EINTR;
        }

      /* If we've taken a count from the semaphore, we have "reserved" the struct
       * but now we need to pop it off of the free list. We need to re-lock the
       * MAC in order to ensure this happens correctly.
      ret = mac802154_lock(priv, allow_interrupt);
Loading full blame...