コード例 #1
0
ファイル: nwk_api.c プロジェクト: hoanibryson/legacyCode
smplStatus_t SMPL_LinkListen(linkID_t *linkID)
{
  uint8_t  radioState = MRFI_GetRadioState();
  uint16_t i;
  linkID_t locLinkID;

  /* Set the context. We want to reject any link frames received if
   * we're not listening. For example if we're an AP we are in
   * promiscuous mode and we'll see any broadcast link frames.
   */
  nwk_setListenContext(LINK_LISTEN_ON);

  NWK_CHECK_FOR_SETRX(radioState);

  for (i=0; i<LINKLISTEN_POLL_COUNT; ++i)
  {
    /* check the semaphore. local port is assigned when the reply is sent. */
    if ((locLinkID=nwk_getLocalLinkID()))
    {
      break;
    }
    NWK_DELAY(LINKLISTEN_POLL_PERIOD_MS);
  }

  NWK_CHECK_FOR_RESTORE_STATE(radioState);

  /* If the listen is terminated without hearing a message and setting a
   * link ID the listen context must be explicitly turned off.
   */
  if (!(locLinkID))
  {
    nwk_setListenContext(LINK_LISTEN_OFF);
    return SMPL_TIMEOUT;
  }

  *linkID = locLinkID;

  return SMPL_SUCCESS;
}
コード例 #2
0
/******************************************************************************
 * @fn          nwk_scanForChannels
 *
 * @brief       Scan for channels by sending a ping frame on each channel in the
 *              channel table and listen for a reply.
 *
 * input parameters
 * @param  channels    - pointer to area to receive list of channels from which
 *                       ping replies were received.
 *
 * output parameters
 * @param   channels   - populated list of channels.
 *
 * @return   statuis of operation..
 */
uint8_t nwk_scanForChannels(freqEntry_t *channels)
{
  uint8_t      msg[FREQ_REQ_PING_FRAME_SIZE], i, num=0, notBcast = 1;
  addr_t      *apAddr, retAddr;
  uint8_t      radioState = MRFI_GetRadioState();
  freqEntry_t  chan;
  freqEntry_t  curChan;

  union
  {
    ioctlRawSend_t    send;
    ioctlRawReceive_t recv;
  } ioctl_info;

  nwk_getChannel(&curChan);

  /* send to AP. If we don't know AP address, broadcast. */
  apAddr = (addr_t *)nwk_getAPAddress();
  if (!apAddr)
  {
    apAddr = (addr_t *)nwk_getBCastAddress();
    notBcast = 0;
  }

  for (i=0; i<NWK_FREQ_TBL_SIZE; ++i)
  {
    chan.logicalChan = i;

    nwk_setChannel(&chan);

    ioctl_info.send.addr = apAddr;
    ioctl_info.send.msg  = msg;
    ioctl_info.send.len  = sizeof(msg);
    ioctl_info.send.port = SMPL_PORT_FREQ;

    msg[FB_APP_INFO_OS] = FREQ_REQ_PING;
    msg[FB_TID_OS]      = sTid;

    SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send);

    ioctl_info.recv.port = SMPL_PORT_FREQ;
    ioctl_info.recv.msg  = msg;
    ioctl_info.recv.addr = &retAddr;

    NWK_CHECK_FOR_SETRX(radioState);
    NWK_REPLY_DELAY();
    NWK_CHECK_FOR_RESTORE_STATE(radioState);

    if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv))
    {
      /* Once we know the Access Point we're related to we only accept
       * ping replies from that one.
       */
      if (!notBcast || (notBcast && !memcmp(&retAddr, apAddr, NET_ADDR_SIZE)))
      {
        channels[num++].logicalChan = i;
      }
    }

    sTid++;
    if (num && notBcast)
    {
      /* we're done...only one possible channel if we know the AP address. */
      break;
    }
    /* TODO: process encryption stuff */
  }

  /* reset original channel */
  nwk_setChannel(&curChan);

  return num;
}
コード例 #3
0
ファイル: nwk_api.c プロジェクト: hoanibryson/legacyCode
/**************************************************************************************
 * @fn          SMPL_Receive
 *
 * @brief       Receive a message from a peer application.
 *
 * input parameters
 * @param   lid     - Link ID (port) from application
 *
 *
 * output parameters
 * @param   msg     - pointer to where received message should be copied.
 *                    buffer should be of size == MAX_APP_PAYLOAD
 * @param   len     - pointer to receive length of received message
 *
 * @return    Status of operation.
 *            Caller should not use the value returned in 'len' to decide
 *            whether there is a frame or not. It could be useful to the
 *            Caller to distinguish between no frame and a frame with no data.
 *            For example, in the polling case a frame with no application payload
 *            is the way the AP conveys that there are no frames waiting.
 *
 *              SMPL_SUCCESS
 *
 *              SMPL_BAD_PARAM  No valid Connection Table entry for Link ID
 *                              Data in Connection Table entry bad
 *              SMPL_NO_FRAME   No frame received.
 *              SMPL_NO_PAYLOAD Frame received with no payload (not necessarily
 *                              an error and could be deduced by application
 *                              because the returned length will be 0)
 *
 *            Polling device only:
 *
 *              SMPL_TIMEOUT        No response from Access Point
 *              SMPL_NO_AP_ADDRESS  Access Point address unknown
 *              SMPL_TX_CCA_FAIL    Could not send poll frame
 *              SMPL_NOMEM          No memory in output frame queue
 *              SMPL_NO_CHANNEL     Frequency Agility enabled and could not find channel
 */
smplStatus_t SMPL_Receive(linkID_t lid, uint8_t *msg, uint8_t *len)
{
  connInfo_t  *pCInfo = nwk_getConnInfo(lid);
  smplStatus_t rc = SMPL_BAD_PARAM;
  rcvContext_t rcv;

  if (!pCInfo || ((rc=nwk_checkConnInfo(pCInfo, CHK_RX)) != SMPL_SUCCESS))
  {
    return rc;
  }

  rcv.type  = RCV_APP_LID;
  rcv.t.lid = lid;

#if defined(RX_POLLS)
  {
    uint8_t numChans  = 1;
#if defined(FREQUENCY_AGILITY)
    freqEntry_t chans[NWK_FREQ_TBL_SIZE];
    uint8_t     scannedB4 = 0;
#endif

    do
    {
      uint8_t radioState = MRFI_GetRadioState();

      /* I'm polling. Do the poll to stimulate the sending of a frame. If the
       * frame has application length of 0 it means there were no frames.  If
       * no reply is received infer that the channel is changed. We then need
       * to scan and then retry the poll on each channel returned.
       */
      if (SMPL_SUCCESS != (rc=nwk_poll(pCInfo->portRx, pCInfo->peerAddr)))
      {
        /* for some reason couldn't send the poll out. */
        return rc;
      }

      /* do this before code block below which may reset it. */
      numChans--;

      /* Wait until there's a frame. if the len is 0 then return SMPL_NO_FRAME
       * to the caller. In the poll case the AP always sends something.
       */
      NWK_CHECK_FOR_SETRX(radioState);
      NWK_REPLY_DELAY();
      NWK_CHECK_FOR_RESTORE_STATE(radioState);

      /* TODO: deal with pending */
      rc = nwk_retrieveFrame(&rcv, msg, len, 0, 0);

#if defined(FREQUENCY_AGILITY)
      if (SMPL_SUCCESS == rc)
      {
        /* we received something... */
        return (*len) ? SMPL_SUCCESS : SMPL_NO_PAYLOAD;
      }

      /* No reply. scan for other channel(s) if we haven't already. Then set
       * one and try again.
       */
      if (!scannedB4)
      {
        numChans  = nwk_scanForChannels(chans);
        scannedB4 = 1;
      }
      if (numChans)
      {
        nwk_setChannel(&chans[numChans-1]);
      }
#else /*  FREQUENCY_AGILITY */
      return (*len) ? rc : ((SMPL_SUCCESS == rc) ? SMPL_NO_PAYLOAD : SMPL_TIMEOUT);
#endif
    } while (numChans);
  }

#if defined(FREQUENCY_AGILITY)
  return SMPL_NO_CHANNEL;
#endif

#else  /* RX_POLLS */
  return nwk_retrieveFrame(&rcv, msg, len, 0, 0);
#endif  /* RX_POLLS */
}
コード例 #4
0
ファイル: nwk_api.c プロジェクト: hoanibryson/legacyCode
/******************************************************************************
 * @fn          SMPL_SendOpt
 *
 * @brief       Send a message to a peer application.
 *
 * input parameters
 * @param   lid     - Link ID (port) from application
 * @param   msg     - pointer to message from app to be sent
 * @param   len     - length of enclosed message
 * @param   options - Transmit options (bit map)
 *
 * output parameters
 *
 * @return   Status of operation. On a filaure the frame buffer is discarded
 *           and the Send call must be redone by the app.
 *             SMPL_SUCCESS
 *             SMPL_BAD_PARAM    No valid Connection Table entry for Link ID
 *                               Data in Connection Table entry bad
 *                               No message or message too long
 *             SMPL_NOMEM        No room in output frame queue
 *             SMPL_TX_CCA_FAIL  CCA failure.
 *             SMPL_NO_ACK       If application auto acknowledgement enabled
 *                               and no acknowledgement is received
 */
smplStatus_t SMPL_SendOpt(linkID_t lid, uint8_t *msg, uint8_t len, txOpt_t options)
{
  frameInfo_t  *pFrameInfo;
  connInfo_t   *pCInfo     = nwk_getConnInfo(lid);
  smplStatus_t  rc         = SMPL_BAD_PARAM;
  uint8_t       radioState;
  uint8_t       ackreq     = 0;
#if defined(ACCESS_POINT)
  uint8_t  loc;
#endif
  radioState = MRFI_GetRadioState();
  /* we have the connection info for this Link ID. make sure it is valid. */
   if (!pCInfo || ((rc=nwk_checkConnInfo(pCInfo, CHK_TX)) != SMPL_SUCCESS))
  {
    return rc;
  }

  /* parameter sanity check... */
  if (!msg || (len > MAX_APP_PAYLOAD))
  {
    return rc;
  }

  /* Build an outgoing message frame destined for the port from the
   * connection info using the destination address also from the
   * connection info.
   */
  if (SMPL_TXOPTION_NONE == options)
  {
    pFrameInfo = nwk_buildFrame(pCInfo->portTx, msg, len, pCInfo->hops2target);
  }
#if defined(APP_AUTO_ACK)
  else if (options & SMPL_TXOPTION_ACKREQ)
  {
    if (SMPL_LINKID_USER_UUD != lid)
    {
      pFrameInfo = nwk_buildAckReqFrame(pCInfo->portTx, msg, len, pCInfo->hops2target, &pCInfo->ackTID);
      ackreq     = 1;
    }
    else
    {
      /* can't request an ack on the UUD link ID */
      return SMPL_BAD_PARAM;
    }
  }
#endif  /* APP_AUTO_ACK */
  else
  {
    return SMPL_BAD_PARAM;
  }

  if (!pFrameInfo)
  {
    return SMPL_NOMEM;
  }
  memcpy(MRFI_P_DST_ADDR(&pFrameInfo->mrfiPkt), pCInfo->peerAddr, NET_ADDR_SIZE);

#if defined(SMPL_SECURE)
  {
    uint32_t *pUL = 0;

    if (pCInfo->thisLinkID != SMPL_LINKID_USER_UUD)
    {
      pUL = &pCInfo->connTxCTR;
    }
    nwk_setSecureFrame(&pFrameInfo->mrfiPkt, len, pUL);
  }
#endif  /* SMPL_SECURE */

#if defined(ACCESS_POINT)
  /* If we are an AP trying to send to a polling device, don't do it.
   * See if the target is a store-and-forward client.
   */
  if (nwk_isSandFClient(MRFI_P_DST_ADDR(&pFrameInfo->mrfiPkt), &loc))
  {
     pFrameInfo->fi_usage = FI_INUSE_UNTIL_FWD;
     return SMPL_SUCCESS;
  }
  else
#endif  /* ACCESS_POINT */
  {
    rc = nwk_sendFrame(pFrameInfo, MRFI_TX_TYPE_CCA);
  }

#if !defined(APP_AUTO_ACK)
  /* save a little code space with this #if */
  (void) ackreq;    /* keep compiler happy */
  return rc;
#else
  /* we're done if the send failed or no ack requested. */
  if (SMPL_SUCCESS != rc || !ackreq)
  {
    return rc;
  }

  NWK_CHECK_FOR_SETRX(radioState);
  NWK_REPLY_DELAY();
  NWK_CHECK_FOR_RESTORE_STATE(radioState);

  {
    bspIState_t intState;

    /* If the saved TID hasn't been reset then we never got the ack. */
    BSP_ENTER_CRITICAL_SECTION(intState);
    if (pCInfo->ackTID)
    {
      pCInfo->ackTID = 0;
      rc = SMPL_NO_ACK;
    }
    BSP_EXIT_CRITICAL_SECTION(intState);
  }

  return rc;
#endif  /* APP_AUTO_ACK */
}
コード例 #5
0
ファイル: nwk_ping.c プロジェクト: ApertureLabsLtd/ChronIC
smplStatus_t nwk_ping(linkID_t lid)
{
    connInfo_t  *pCInfo   = nwk_getConnInfo(lid);
    smplStatus_t rc       = SMPL_BAD_PARAM;
    uint8_t done     = 0;
    uint8_t repeatIt = 2;
    uint8_t msg[MAX_PING_APP_FRAME];
    uint8_t radioState = MRFI_GetRadioState();

    union
    {
        ioctlRawSend_t send;
        ioctlRawReceive_t recv;
    } ioctl_info;

    if (!pCInfo || (SMPL_LINKID_USER_UUD == lid))
    {
        /* either link ID bogus or tried to ping the unconnected user datagram link ID. */
        return rc;
    }

    do
    {
#if defined(FREQUENCY_AGILITY) && !defined(ACCESS_POINT)
        uint8_t i, numChan;
        freqEntry_t channels[NWK_FREQ_TBL_SIZE];

        if (repeatIt == 2)
        {
            /* If FA enabled, first time through set up so that the 'for'
             * loop checks the current channel. This saves time (no scan)
             * and is very likely to succeed. Populate the proper strucure.
             */
            SMPL_Ioctl(IOCTL_OBJ_FREQ, IOCTL_ACT_GET, channels);
            numChan = 1;
        }
        else
        {
            /* If we get here we must scan for the channel we're now on */
            if (!(numChan = nwk_scanForChannels(channels)))
            {
                return SMPL_NO_CHANNEL;
            }
        }
        /* Either we scan next time through or we're done */
        repeatIt--;

        /* this loop Pings on each channel (probably only 1) looking
         * for peer.
         */
        for (i = 0; i < numChan && !done; ++i)
        {
            nwk_setChannel(&channels[i]);
#else
        {
            repeatIt = 0;
#endif      /* defined(FREQUENCY_AGILITY) && !defined(ACCESS_POINT) */

            ioctl_info.send.addr = (addr_t *)pCInfo->peerAddr;
            ioctl_info.send.msg  = msg;
            ioctl_info.send.len  = sizeof(msg);
            ioctl_info.send.port = SMPL_PORT_PING;

            /* fill in msg */
            msg[PB_REQ_OS] = PING_REQ_PING;
            msg[PB_TID_OS] = sTid;

            SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send);

            ioctl_info.recv.port = SMPL_PORT_PING;
            ioctl_info.recv.msg  = msg;
            ioctl_info.recv.addr = 0;

            NWK_CHECK_FOR_SETRX(radioState);
            NWK_REPLY_DELAY();
            NWK_CHECK_FOR_RESTORE_STATE(radioState);

            if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv))
            {
                repeatIt = 0;
                done     = 1;
                sTid++; /* guard against duplicates */
            }
        }
    } while (repeatIt);

    return done ? SMPL_SUCCESS : SMPL_TIMEOUT;

}

/******************************************************************************
 * @fn          smpl_send_ping_reply
 *
 * @brief       Send a reply to a ping request.
 *
 * input parameters
 * @param   frame     - pointer to frame containing request
 *
 * output parameters
 *
 * @return   void
 */

static void smpl_send_ping_reply(mrfiPacket_t *frame)
{
    frameInfo_t *pOutFrame;

    /* Build the reply frame. The application payload is the one included in the
     * received frame payload.
     */
    if (pOutFrame =
            nwk_buildFrame(SMPL_PORT_PING, MRFI_P_PAYLOAD(frame) + F_APP_PAYLOAD_OS,
                           MRFI_GET_PAYLOAD_LEN(frame) - F_APP_PAYLOAD_OS, MAX_HOPS))
    {
        /* destination address is the source adddress of the received frame. */
        memcpy(MRFI_P_DST_ADDR(&pOutFrame->mrfiPkt), MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE);

        /* turn on the reply bit in the application payload */
        *(MRFI_P_PAYLOAD(&pOutFrame->mrfiPkt) + F_APP_PAYLOAD_OS + PB_REQ_OS) |= NWK_APP_REPLY_BIT;
#ifdef SMPL_SECURE
        nwk_setSecureFrame(&pOutFrame->mrfiPkt, MRFI_GET_PAYLOAD_LEN(frame) - F_APP_PAYLOAD_OS, 0);
#endif  /* SMPL_SECURE */
        nwk_sendFrame(pOutFrame, MRFI_TX_TYPE_FORCED);
    }
}
コード例 #6
0
smplStatus_t nwk_link(linkID_t *lid)
{
    uint8_t msg[LINK_FRAME_SIZE];
    connInfo_t   *pCInfo = nwk_getNextConnection();
    smplStatus_t rc;

    if (pCInfo)
    {
        addr_t addr;
        union
        {
            ioctlRawSend_t send;
            ioctlRawReceive_t recv;
        } ioctl_info;

        if (!nwk_allocateLocalRxPort(LINK_SEND, pCInfo))
        {
            nwk_freeConnection(pCInfo);
            return SMPL_NOMEM;
        }

        memcpy(addr.addr, nwk_getBCastAddress(), NET_ADDR_SIZE);
        ioctl_info.send.addr = &addr;
        ioctl_info.send.msg  = msg;
        ioctl_info.send.len  = sizeof(msg);
        ioctl_info.send.port = SMPL_PORT_LINK;

        /* Put link token in */
        nwk_putNumObjectIntoMsg((void *)&sLinkToken, msg + L_LINK_TOKEN_OS, sizeof(sLinkToken));

        /* set port to which the remote device should send */
        msg[L_RMT_PORT_OS] = pCInfo->portRx;

        /* set the transaction ID. this allows target to figure out duplicates */
        msg[LB_TID_OS] = sTid;

        /* set my Rx type */
        msg[L_MY_RXTYPE_OS] = nwk_getMyRxType();

        /* set request byte */
        msg[LB_REQ_OS] = LINK_REQ_LINK;

        /* protocol version number */
        msg[L_PROTOCOL_VERSION_OS] = nwk_getProtocolVersion();

#if defined(SMPL_SECURE)
        pCInfo->connTxCTR = MRFI_RandomByte()                   | \
            ((uint32_t)(MRFI_RandomByte()) << 8)  | \
            ((uint32_t)(MRFI_RandomByte()) << 16) | \
            ((uint32_t)(MRFI_RandomByte()) << 24);

        nwk_putNumObjectIntoMsg((void *)&pCInfo->connTxCTR, (void *)&msg[L_CTR_OS], 4);
#endif


        if (SMPL_SUCCESS != (rc = SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send)))
        {
            return rc;
        }

        {
            uint8_t radioState = MRFI_GetRadioState();

            ioctl_info.recv.port = SMPL_PORT_LINK;
            ioctl_info.recv.msg  = msg;
            ioctl_info.recv.addr = (addr_t *)pCInfo->peerAddr;

            NWK_CHECK_FOR_SETRX(radioState);
            NWK_REPLY_DELAY();
            NWK_CHECK_FOR_RESTORE_STATE(radioState);

            if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv))
            {
                uint8_t firstByte = msg[LB_REQ_OS] & (~NWK_APP_REPLY_BIT);

                /* Sanity check for correct reply frame. Older version
                 * has the length instead of the request as the first byte.
                 */
                if ((firstByte != LINK_REQ_LINK) &&
                    (firstByte != LINK_REPLY_LEGACY_MSG_LENGTH)
                    )
                {
                    /* invalidate connection object */
                    nwk_freeConnection(pCInfo);
                    return SMPL_NO_LINK;

                }
            }
            else
            {
                /* no successful receive */
                nwk_freeConnection(pCInfo);
                return SMPL_TIMEOUT;
            }

            pCInfo->connState = CONNSTATE_CONNECTED;
            pCInfo->portTx    = msg[LR_RMT_PORT_OS]; /* link reply returns remote port */
            *lid              = pCInfo->thisLinkID;  /* return our local port number */

            /* Set hop count. If it's a polling device set the count to the
             * distance to the AP. Otherwise, set it to the max less the remaining
             * which will be the path taken for this frame. It will be no worse
             * then tha max and probably will be better.
             */
            if (F_RX_TYPE_POLLS == msg[LR_MY_RXTYPE_OS])
            {
                pCInfo->hops2target = MAX_HOPS_FROM_AP;
            }
            else
            {
                /* Can't really use this trick because the device could move. If the
                 * devices are all static this may work unless the initial reception
                 * was marginal.
                 */
#if defined(DEVICE_DOES_NOT_MOVE)
                pCInfo->hops2target = MAX_HOPS - ioctl_info.recv.hopCount;
#else
                pCInfo->hops2target = MAX_HOPS;
#endif
            }

#if defined(SMPL_SECURE)
            nwk_getNumObjectFromMsg((void *)&msg[LR_CTR_OS], (void *)&pCInfo->connRxCTR, 4);
#endif
        }

        /* guard against duplicates... */
        ++sTid;
        if (!sTid)
        {
            sTid = 1;
        }
        return SMPL_SUCCESS;
    }

    return SMPL_NOMEM;
}
コード例 #7
0
smplStatus_t nwk_unlink(linkID_t lid)
{
    uint8_t msg[UNLINK_FRAME_SIZE];
    connInfo_t  *pCInfo = nwk_getConnInfo(lid);
    smplStatus_t rc     = SMPL_SUCCESS;
    addr_t addr;

    union
    {
        ioctlRawSend_t send;
        ioctlRawReceive_t recv;
    } ioctl_info;

    /* is there connection info? */
    if (!pCInfo || (lid == SMPL_LINKID_USER_UUD))
    {
        return SMPL_BAD_PARAM;
    }

    /* set request byte */
    msg[LB_REQ_OS] = LINK_REQ_UNLINK;

    /* set the transaction ID. this allows target to figure out duplicates */
    msg[LB_TID_OS] = sTid;

    /* remote port to be sent in message to help match connection */
    msg[UL_RMT_PORT_OS] = pCInfo->portRx;

    /* setup for ioctl raw I/O */
    memcpy(addr.addr, pCInfo->peerAddr, NET_ADDR_SIZE);
    ioctl_info.send.addr = &addr;
    ioctl_info.send.msg  = msg;
    ioctl_info.send.len  = sizeof(msg);
    ioctl_info.send.port = SMPL_PORT_LINK;

    SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send);

    {
        uint8_t spin       = NWK_RX_RETRY_COUNT;
        uint8_t radioState = MRFI_GetRadioState();

        ioctl_info.recv.port = SMPL_PORT_LINK;
        ioctl_info.recv.msg  = msg;
        ioctl_info.recv.addr = (addr_t *)0;

        do
        {
            NWK_CHECK_FOR_SETRX(radioState);
            NWK_REPLY_DELAY();
            NWK_CHECK_FOR_RESTORE_STATE(radioState);

            if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv))
            {
                if ((msg[LB_REQ_OS] & (~NWK_APP_REPLY_BIT)) == LINK_REQ_UNLINK)
                {
                    rc = (smplStatus_t)msg[ULR_RESULT_OS];
                    break;
                }
            }
            if (!spin)
            {
                rc = SMPL_TIMEOUT;
                break;
            }
            --spin;
        } while (1);

        /* it's ok to unconditionally invalidate connection object */
        nwk_freeConnection(pCInfo);
    }
    return rc;
}
コード例 #8
0
ファイル: nwk_join.c プロジェクト: DroningOn/ECE411
/******************************************************************************
 * @fn          nwk_join
 *
 * @brief       Join functioanlity for non-AP devices. Send the Join token
 *              and wait for the reply.
 *
 * input parameters
 *
 * output parameters
 *
 * @return   Status of operation.
 */
smplStatus_t nwk_join(void)
{
  uint8_t      msg[JOIN_FRAME_SIZE];
  uint32_t     linkToken;
  addr_t       apAddr;
  uint8_t      radioState = MRFI_GetRadioState();
  smplStatus_t rc = SMPL_NO_JOIN;
  union
  {
    ioctlRawSend_t    send;
    ioctlRawReceive_t recv;
  } ioctl_info;

#if defined( FREQUENCY_AGILITY )
  uint8_t  i, numChan;
  freqEntry_t channels[NWK_FREQ_TBL_SIZE];

  if (!(numChan=nwk_scanForChannels(channels)))
  {
    return SMPL_NO_CHANNEL;
  }

  for (i=0; i<numChan; ++i)
  {
    nwk_setChannel(&channels[i]);
#else
  {
#endif

    ioctl_info.send.addr = (addr_t *)nwk_getBCastAddress();
    ioctl_info.send.msg  = msg;
    ioctl_info.send.len  = sizeof(msg);
    ioctl_info.send.port = SMPL_PORT_JOIN;

    /* Put join token in */
    nwk_putNumObjectIntoMsg((void *)&sJoinToken, msg+J_JOIN_TOKEN_OS, sizeof(sJoinToken));
    /* set app info byte */
    msg[JB_REQ_OS] = JOIN_REQ_JOIN;
    msg[JB_TID_OS] = sTid;
    /* Set number of connections supported. Used only by AP if it is
     * a data hub.
     */
    msg[J_NUMCONN_OS] = NUM_CONNECTIONS;
    /* protocol version number */
    msg[J_PROTOCOL_VERSION_OS] = nwk_getProtocolVersion();

    SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &ioctl_info.send);

    ioctl_info.recv.port = SMPL_PORT_JOIN;
    ioctl_info.recv.msg  = msg;
    ioctl_info.recv.addr = &apAddr;    /* save AP address from reply */

    NWK_CHECK_FOR_SETRX(radioState);
    NWK_REPLY_DELAY();
    NWK_CHECK_FOR_RESTORE_STATE(radioState);

    if (SMPL_SUCCESS == SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_READ, &ioctl_info.recv))
    {
      uint8_t firstByte = msg[JB_REQ_OS] & (~NWK_APP_REPLY_BIT);

      /* Sanity check for correct reply frame. Older version
       * has the length instead of the request as the first byte.
       */
      if ((firstByte == JOIN_REQ_JOIN) ||
          (firstByte == JOIN_REPLY_LEGACY_MSG_LENGTH)
         )
      {
        /* join reply returns link token */
        memcpy(&linkToken, msg+JR_LINK_TOKEN_OS, sizeof(linkToken));

        nwk_setLinkToken(linkToken);
        /* save AP address */
        nwk_setAPAddress(&apAddr);
        sTid++;   /* guard against duplicates */
        rc = SMPL_SUCCESS;
#if defined( FREQUENCY_AGILITY )
        break;
#endif
      }
    }
    /* TODO: process encryption stuff */
  }

  return rc;

}

#endif /* ACCESS_POINT */

/******************************************************************************
 * @fn          nwk_processJoin
 *
 * @brief       Processes a Join frame. If this is a reply let it go to the
 *              application. Otherwise generate and send the reply.
 *
 * input parameters
 * @param   frame     - Pointer to Join frame
 *
 * output parameters
 *
 * @return   Keep frame for application, release frame, or replay frame.
 */
fhStatus_t nwk_processJoin(mrfiPacket_t *frame)
{
  fhStatus_t rc = FHS_RELEASE;
  uint8_t    replyType;

  /* Make sure this is a reply and see if we sent this. Validate the
   * packet for reception by client app.
   */
  if (SMPL_MY_REPLY == (replyType=nwk_isValidReply(frame, sTid, JB_REQ_OS, JB_TID_OS)))
  {
    /* It's a match and it's a reply. Validate the received packet by
     * returning a 1 so it can be received by the client app.
     */
    MRFI_PostKillSem();
    rc = FHS_KEEP;
  }
#if defined(ACCESS_POINT)
  else if (SMPL_A_REPLY == replyType)
  {
    /* No match. If I'm not an ED this is a reply that should be passed on. */
    rc = FHS_REPLAY;
  }
  else
  {
    /* Send reply if we're an Access Point otherwise ignore the frame. */
    if ((SMPL_NOT_REPLY == replyType) && sJoinOK)
    {
      handleJoinRequest(frame);
    }
  }
#elif defined(RANGE_EXTENDER)
  else
  {