e08610318 发表于 2012-12-14 19:38

simpliciTI代码讨论

/******************************************************************************
* @fn          dispatchFrame
*
* @brief       Received frame looks OK so far. Dispatch to either NWK app by
*            invoking the handler or the user's app by simply leaving the
*            frame in the queue and letting the app poll the port.
*
* input parameters
* @param   fiPtr    - frameInfo_t pointer to received frame
*
* output parameters
*
* @return   void
*/
static void dispatchFrame(frameInfo_t *fiPtr)
{
uint8_t   port       = GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_PORT_OS);
uint8_t   nwkAppSize = sizeof(func)/sizeof(func);
fhStatus_trc;
linkID_t    lid;
#if defined(ACCESS_POINT)
uint8_t loc;
#endif
#if !defined(END_DEVICE)
uint8_t isForMe;
#endif

/* be sure it's not an echo... */
if (!memcmp(MRFI_P_SRC_ADDR(&fiPtr->mrfiPkt), sMyAddr, NET_ADDR_SIZE))
{
    fiPtr->fi_usage = FI_AVAILABLE;
    return;
}

/* Make sure encyrption bit conforms to our security support context. */
#if defined(SMPL_SECURE)
if (!(GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_ENCRYPT_OS)))
{
    /* Encyrption bit is not on when when it should be */
    fiPtr->fi_usage = FI_AVAILABLE;
    return;
}
#else
if (GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_ENCRYPT_OS))
{
    /* Encyrption bit is on when when it should not be */
    fiPtr->fi_usage = FI_AVAILABLE;
    return;
}
#endif/* SMPL_SECURE */

/* If it's a network application port dispatch to service routine. Dispose
   * of frame depending on return code.
   */
if (port && (port <= nwkAppSize))
{
#if defined(SMPL_SECURE)
    /* Non-connection-based frame. We can decode here if it was encrypted */
    if (!nwk_getSecureFrame(&fiPtr->mrfiPkt, MRFI_GET_PAYLOAD_LEN(&fiPtr->mrfiPkt) - F_SEC_CTR_OS, 0))
    {
      fiPtr->fi_usage = FI_AVAILABLE;
      return;
    }
#endif
    rc = func(&fiPtr->mrfiPkt);
    if (FHS_KEEP == rc)
    {
      fiPtr->fi_usage = FI_INUSE_UNTIL_DEL;
    }
#if !defined(END_DEVICE)
    else if (FHS_REPLAY == rc)
    {
      /* an AP or an RE could be relaying a NWK application frame... */
      nwk_replayFrame(fiPtr);
    }
#endif
    else/* rc == FHS_RELEASE (default...) */
    {
      fiPtr->fi_usage = FI_AVAILABLE;
    }
    return;
}
/* sanity check */
else if ((port != SMPL_PORT_USER_BCAST) && ((port < PORT_BASE_NUMBER) || (port > SMPL_PORT_STATIC_MAX)))
{
    /* bogus port. drop frame */
    fiPtr->fi_usage = FI_AVAILABLE;
    return;
}

/* At this point we know the target is a user app. If this is an end device
   * and we got this far save the frame and we're done. If we're an AP there
   * are 3 cases: it's for us, it's for s store-and-forward client, or we need
   * to replay the frame. If we're and RE and the frame didn't come from an RE
   * and it's not for us, replay the frame.
   */

#if defined(END_DEVICE)
/* If we're s polling end device we only accept application frames from
   * the AP. This prevents duplicate reception if we happen to be on when
   * a linked peer sends.
   */
#if defined(RX_POLLS)
if (F_TX_DEVICE_ED != GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_TX_DEVICE))
{
    if (nwk_isConnectionValid(&fiPtr->mrfiPkt, &lid))
    {
      fiPtr->fi_usage = FI_INUSE_UNTIL_DEL;
    }
    else
    {
      fiPtr->fi_usage = FI_AVAILABLE;
    }
}
else
{
    fiPtr->fi_usage = FI_AVAILABLE;
}
#else
/* it's destined for a user app. */
if (nwk_isConnectionValid(&fiPtr->mrfiPkt, &lid))
{
    fiPtr->fi_usage = FI_INUSE_UNTIL_DEL;
    if (spCallback && spCallback(lid))
    {
      fiPtr->fi_usage = FI_AVAILABLE;
      return;
    }
}
else
{
    fiPtr->fi_usage = FI_AVAILABLE;
}
#endif/* RX_POLLS */

#else   /* END_DEVICE */

/* We have an issue if the frame is broadcast to the UUD port. The AP (or RE) must
   * handle this frame as if it were the target in case there is an application
   * running that is listening on that port. But if it's a broadcast it must also be
   * replayed. It isn't enough just to test for the UUD port because it could be a
   * directed frame to another device. We must check explicitly for broadcast
   * destination address.
   */
isForMe = !memcmp(sMyAddr, MRFI_P_DST_ADDR(&fiPtr->mrfiPkt), NET_ADDR_SIZE);
if (isForMe || ((port == SMPL_PORT_USER_BCAST) && !memcmp(nwk_getBCastAddress(), MRFI_P_DST_ADDR(&fiPtr->mrfiPkt), NET_ADDR_SIZE)))
{
    /* The folllowing test will succeed for the UUD port regardless of the
   * source address.
   */
    if (nwk_isConnectionValid(&fiPtr->mrfiPkt, &lid))
    {
      /* If this is for the UUD port and we are here then the device is either
       * an AP or an RE. In either case it must replay the UUD port frame if the
       * frame is not "for me". But it also must handle it since it could have a
       * UUD-listening application. Do the reply first and let the subsequent code
       * correctly set the frame usage state. Note that the routine return can be
       * from this code block. If not it will drop through to the bottom without
       * doing a replay.
       */
      /* Do I need to replay it? */
      if (!isForMe)
      {
      /* must be a broadcast for the UUD port */
      nwk_replayFrame(fiPtr);
      }
      /* OK. Now I handle it... */
      fiPtr->fi_usage = FI_INUSE_UNTIL_DEL;
      if (spCallback && spCallback(lid))
      {
      fiPtr->fi_usage = FI_AVAILABLE;
      return;
      }
    }
    else
    {
      fiPtr->fi_usage = FI_AVAILABLE;
    }
}
#if defined( ACCESS_POINT )
/* Check to see if we need to save this for a S and F client. Otherwise,
   * if it's not for us, get rid of it.
   */
else if (nwk_isSandFClient(MRFI_P_DST_ADDR(&fiPtr->mrfiPkt), &loc))
{
    /* Don't bother if it is a duplicate frame or if it's a forwarded frame
   * echoed back from an RE.
   */
    if (!isDupSandFFrame(&fiPtr->mrfiPkt) &&
      !(GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_FWD_FRAME))
       )
    {
#if defined(APP_AUTO_ACK)
      /* Make sure ack request bit is off. Sender will have gone away. */
      PUT_INTO_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_ACK_REQ, 0);
#endif
      fiPtr->fi_usage = FI_INUSE_UNTIL_FWD;
    }
    else
    {
      fiPtr->fi_usage = FI_AVAILABLE;
    }
}
else if (GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_TX_DEVICE) == F_TX_DEVICE_AP)
{
    /* I'm an AP and this frame came from an AP. Don't replay. */
    fiPtr->fi_usage = FI_AVAILABLE;
}
#elif defined( RANGE_EXTENDER )
else if (GET_FROM_FRAME(MRFI_P_PAYLOAD(&fiPtr->mrfiPkt), F_TX_DEVICE) == F_TX_DEVICE_RE)
{
    /* I'm an RE and this frame came from an RE. Don't replay. */
    fiPtr->fi_usage = FI_AVAILABLE;
}
#endif
else
{
    /* It's not for me and I'm either an AP or I'm an RE and the frame
   * didn't come from an RE. Replay the frame.
   */
    nwk_replayFrame(fiPtr);
}
#endif/* !END_DEVICE */
return;
}

红色部分代码,迷惑......ctrl+shift+f 找了好久,都不知道func怎么来的。看过的指导下......

adams.gh 发表于 2012-12-15 22:38

肯定是有个 全局数组 func[ ]啊

wuyingte 发表于 2012-12-17 22:25

多看几遍。
页: [1]
查看完整版本: simpliciTI代码讨论