/****************************************************************************** * @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; }
/****************************************************************************** * @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; }