/****************************************************************************** * @fn SMPL_Ioctl * * @brief This routine supplies the SimpliciTI IOCTL support. * * input parameters * @param object - The IOCTL target object * @param action - The IOCTL target action on the object * @param val - pointer to value. exact forn depends on object type. * * output parameters * * @return Status of action. Value depends on object, action, and result. * * SMPL_BAD_PARAM is returned if this API is called before * initialization and the object is not one of * the valid exceptions. */ smplStatus_t SMPL_Ioctl(ioctlObject_t object, ioctlAction_t action, void *val) { smplStatus_t rc; /* if init hasn't occurred see if access is still valid */ if (!sInit_done && !ioctlPreInitAccessIsOK(object)) { return SMPL_BAD_PARAM; } switch (object) { #if defined(EXTENDED_API) case IOCTL_OBJ_TOKEN: { ioctlToken_t *t = (ioctlToken_t *)val; rc = SMPL_SUCCESS; if (TT_LINK == t->tokenType) { if (IOCTL_ACT_SET == action) { nwk_setLinkToken(t->token.linkToken); } else if (IOCTL_ACT_GET == action) { nwk_getLinkToken(&t->token.linkToken); } else { rc = SMPL_BAD_PARAM; } } else if (TT_JOIN == t->tokenType) { if (IOCTL_ACT_SET == action) { nwk_setJoinToken(t->token.joinToken); } else if (IOCTL_ACT_GET == action) { nwk_getJoinToken(&t->token.joinToken); } else { rc = SMPL_BAD_PARAM; } } else { rc = SMPL_BAD_PARAM; } } break; case IOCTL_OBJ_NVOBJ: rc = nwk_NVObj(action, (ioctlNVObj_t *)val); break; #endif /* EXTENDED_API */ case IOCTL_OBJ_CONNOBJ: rc = nwk_connectionControl(action, val); break; case IOCTL_OBJ_ADDR: if ((IOCTL_ACT_GET == action) || (IOCTL_ACT_SET == action)) { rc = nwk_deviceAddress(action, (addr_t *)val); } else { rc = SMPL_BAD_PARAM; } break; case IOCTL_OBJ_RAW_IO: if (IOCTL_ACT_WRITE == action) { rc = nwk_rawSend((ioctlRawSend_t *)val); } else if (IOCTL_ACT_READ == action) { rc = nwk_rawReceive((ioctlRawReceive_t *)val); } else { rc = SMPL_BAD_PARAM; } break; case IOCTL_OBJ_RADIO: rc = nwk_radioControl(action, val); break; #if defined(ACCESS_POINT) case IOCTL_OBJ_AP_JOIN: rc = nwk_joinContext(action); break; #endif #if defined(FREQUENCY_AGILITY) case IOCTL_OBJ_FREQ: rc = nwk_freqControl(action, val); break; #endif case IOCTL_OBJ_FWVER: if (IOCTL_ACT_GET == action) { memcpy(val, nwk_getFWVersion(), SMPL_FWVERSION_SIZE); rc = SMPL_SUCCESS; } else { rc = SMPL_BAD_PARAM; } break; case IOCTL_OBJ_PROTOVER: if (IOCTL_ACT_GET == action) { *((uint8_t *)val) = nwk_getProtocolVersion(); rc = SMPL_SUCCESS; } else { rc = SMPL_BAD_PARAM; } break; default: rc = SMPL_BAD_PARAM; break; } return rc; }
/****************************************************************************** * @fn smpl_send_join_reply * * @brief Send the Join reply. Include the Link token. If the device is * a polling sleeper put it into the list of store-and-forward * clients. * * input parameters * @param frame - join frame for which a reply is needed...maybe * * output parameters * * @return void */ static void smpl_send_join_reply(mrfiPacket_t *frame) { frameInfo_t *pOutFrame; uint8_t msg[JOIN_REPLY_FRAME_SIZE]; /* Is this a legacy frame? If so continue. Otherwise check verion.*/ if ((MRFI_GET_PAYLOAD_LEN(frame) - F_APP_PAYLOAD_OS) > JOIN_LEGACY_MSG_LENGTH) { /* see if protocol version is correct... */ if (*(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_PROTOCOL_VERSION_OS) != nwk_getProtocolVersion()) { /* Accommodation of protocol version differences can be noted or accomplished here. * Otherwise, no match and the board goes back */ return; } } /* see if join token is correct */ { uint32_t jt; nwk_getNumObjectFromMsg(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_JOIN_TOKEN_OS, &jt, sizeof(jt)); if (jt != sJoinToken) { return; } } /* send reply with tid, the link token, and the encryption context */ { uint32_t linkToken; nwk_getLinkToken(&linkToken); nwk_putNumObjectIntoMsg((void *)&linkToken, msg+JR_LINK_TOKEN_OS, sizeof(linkToken)); } msg[JR_CRYPTKEY_SIZE_OS] = SEC_CRYPT_KEY_SIZE; msg[JB_REQ_OS] = JOIN_REQ_JOIN | NWK_APP_REPLY_BIT; /* sender's tid... */ msg[JB_TID_OS] = *(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+JB_TID_OS); if (pOutFrame = nwk_buildFrame(SMPL_PORT_JOIN, msg, sizeof(msg), MAX_HOPS_FROM_AP)) { /* 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); #ifdef AP_IS_DATA_HUB /* if source device supports ED objects save source address to detect duplicate joins */ if (*(MRFI_P_PAYLOAD(frame)+F_APP_PAYLOAD_OS+J_NUMCONN_OS)) { if (nwk_saveJoinedDevice(frame) && spCallback) { spCallback(0); } } #endif } else { /* oops -- no room left for Tx frame. Don't send reply. */ return; } /* If this device polls we need to provide store-and-forward support */ if (GET_FROM_FRAME(MRFI_P_PAYLOAD(frame),F_RX_TYPE) == F_RX_TYPE_POLLS) { uint8_t loc; /* Check duplicate status */ if (!nwk_isSandFClient(MRFI_P_SRC_ADDR(frame), &loc)) { uint8_t *pNumc = &spSandFContext->curNumSFClients; sfClientInfo_t *pClient = &spSandFContext->sfClients[*pNumc]; /* It's not a duplicate. Save it if there's room */ if (*pNumc < NUM_STORE_AND_FWD_CLIENTS) { memcpy(pClient->clientAddr.addr, MRFI_P_SRC_ADDR(frame), NET_ADDR_SIZE); *pNumc = *pNumc + 1; } else { /* No room left. Just return and don't send reply. */ return; } } else { /* We get here if it's a duplicate. We drop through and send reply. * Reset the S&F marker in the Management application -- we should * assume that the Client reset so the TID will be random. If this is * simply a duplicate frame it causes no harm. */ nwk_resetSFMarker(loc); } } #ifdef SMPL_SECURE nwk_setSecureFrame(&pOutFrame->mrfiPkt, sizeof(msg), 0); #endif /* SMPL_SECURE */ /* It's not S&F or it is but we're OK to send reply. */ nwk_sendFrame(pOutFrame, MRFI_TX_TYPE_FORCED); return; }