/******************************************************************************
 * @fn          change_channel_cmd_is_valid
 *
 * @brief       Check validity of a change channel command frame.
 *
 * input parameters
 * @param   frame  - pointer to frame with command context
 *
 * @return   Returns non-zero if command is valid, otherwise returns 0.
 *           Command is valid if either:
 *             - frame is directed
 *             - frame is from an AP and we know about that AP
 *
 *           It is possible that either we don't know about an AP or that
 *           we do but this frame comes from another AP in range.
 */
static uint8_t change_channel_cmd_is_valid(mrfiPacket_t *frame)
{
  uint8_t rc = 0;
  addr_t const *apAddr;

  /* If this was a directed frame obey the command. */
  if (!memcmp(MRFI_P_DST_ADDR(frame), nwk_getMyAddress(), NET_ADDR_SIZE))
  {
    rc = 1;
  }
  else
  {
    /* Do we know about an AP? If not assume frame bogus. */
    apAddr = nwk_getAPAddress();
    if (apAddr)
    {
      /* Yes, we know about an AP. Is that who sent it? */
      if (!memcmp(apAddr, MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE))
      {
        /* OK. We obey. */
        rc = 1;
      }
    }
  }

  return rc;
}
Beispiel #2
0
/******************************************************************************
 * @fn          nwk_poll
 *
 * @brief       Poll S&F server for any waiting frames.
 *
 * input parameters
 * @param  port  - Port on peer.
 * @param  addr  - SimpliciTI address of peer.
 *
 * output parameters
 *
 * @return   SMPL_SUCCESS
 *           SMPL_NO_AP_ADDRESS - We don't know Access Point's address
 *           SMPL_NOMEM         - no room in output frame queue
 *           SMPL_TX_CCA_FAIL   - CCA failure
 */
smplStatus_t nwk_poll(uint8_t port, uint8_t *addr)
{
  uint8_t        msg[MGMT_POLL_FRAME_SIZE];
  ioctlRawSend_t send;

  msg[MB_APP_INFO_OS] = MGMT_REQ_POLL;
  msg[MB_TID_OS]      = sTid;
  msg[M_POLL_PORT_OS] = port;
  memcpy(msg+M_POLL_ADDR_OS, addr, NET_ADDR_SIZE);

  /* it's OK to increment the TID here because the reply will not be
   * matched based on this number. The reply to the poll comes back
   * to the client port, not the Management port.
   */
  sTid++;

  if (!sAPAddr)
  {
    sAPAddr = nwk_getAPAddress();
    if (!sAPAddr)
    {
      return SMPL_NO_AP_ADDRESS;
    }
  }
  send.addr = (addr_t *)sAPAddr;
  send.msg  = msg;
  send.len  = sizeof(msg);
  send.port = SMPL_PORT_MGMT;

  return SMPL_Ioctl(IOCTL_OBJ_RAW_IO, IOCTL_ACT_WRITE, &send);
}
/******************************************************************************
 * @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;
}