bool emAfPluginCommsHubFunctionTunnelSendData(EmberEUI64 remoteDeviceId, uint16_t headerLen, uint8_t *header, uint16_t dataLen, uint8_t *data) { EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; bool success; uint8_t tunnelIndex; emberAfDebugPrint("CHF: TunnelSendData "); emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId)); emberAfDebugPrint(" ["); emberAfDebugPrintBuffer(header, headerLen, false); emberAfDebugPrintBuffer(data, dataLen, false); emberAfDebugPrintln("]"); tunnelIndex = findTunnelByDeviceId(remoteDeviceId); if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { if (tunnels[tunnelIndex].state == ACTIVE_TUNNEL) { // Add the header to the output buffers to that we don't copy data twice if (headerLen > 0) { MEMCOPY(message, header, headerLen); MEMCOPY(message+headerLen, data, dataLen); data = message; dataLen += headerLen; } status = (tunnels[tunnelIndex].type == CLIENT_TUNNEL) ? emberAfPluginTunnelingClientTransferData(tunnels[tunnelIndex].tunnelId, data, dataLen) : emberAfPluginTunnelingServerTransferData(tunnels[tunnelIndex].tunnelId, data, dataLen); } else if (tunnels[tunnelIndex].state == CLOSED_TUNNEL) { // we'll return failure to this message but we'll start the process // of bring up the tunnel so that if the message is resent the tunnel // should be up. emberAfPluginCommsHubFunctionPrintln("Tunnel Closed: New tunnel is requested for the device."); requestTunnel(tunnelIndex); } } success = (status == EMBER_ZCL_STATUS_SUCCESS); if (!success) { emberAfPluginCommsHubFunctionPrintln("%p%p%p0x%x", "Error: ", "Tunnel SendData failed: ", "Tunneling Status: ", status); } return success; }
bool emAfPluginCommsHubFunctionTunnelDestroy(EmberEUI64 remoteDeviceId) { EmberAfStatus status = EMBER_ZCL_STATUS_NOT_FOUND; uint8_t tunnelIndex; emberAfDebugPrint("CHF: TunnelDestroy "); emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId)); emberAfDebugPrintln(""); tunnelIndex = findTunnelByDeviceId(remoteDeviceId); if (tunnelIndex < EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT) { status = (tunnels[tunnelIndex].type == CLIENT_TUNNEL) ? emberAfPluginTunnelingClientCloseTunnel(tunnels[tunnelIndex].tunnelId) : EMBER_ZCL_STATUS_SUCCESS; if (status == EMBER_ZCL_STATUS_SUCCESS) { tunnels[tunnelIndex].state = UNUSED_TUNNEL; if (tunnelIndex == responsePendingIndex) { responsePendingIndex = EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX; // let the tunnel event handler retry any pending create requests emberEventControlSetActive(emberAfPluginCommsHubFunctionTunnelEventControl); } } } return (status == EMBER_ZCL_STATUS_SUCCESS); }
EmberStatus SimpleCommissioningStart(uint8_t endpoint, bool is_server, const uint16_t *clusters, uint8_t length) { if (!clusters || !length) { // meaningless call if ClusterID array was not passed or its length // is zero return EMBER_BAD_ARGUMENT; } emberAfDebugPrintln("DEBUG: Call for starting commissioning"); if (length > emberBindingTableSize) { // passed more clusters than the binding table may handle // TODO: may be it is worth to track available entries to write in // the binding table emberAfDebugPrint("Warning: ask for bind 0x%X clusters. ", length); emberAfDebugPrintln("Binding table size is 0x%X", emberBindingTableSize); } if (CommissioningStateMachineStatus() != SC_EZ_STOP) { // quite implicit, but if our state machine runs then network // probably busy return EMBER_NETWORK_BUSY; } InitDeviceCommissionInfo(&dev_comm_session, endpoint, is_server, clusters, length); // Wake up our state machine emberEventControlSetActive(StateMachineEvent); return EMBER_SUCCESS; }
/*! Callback for IEEE address Request */ static void ProcessEUI64Discovery(const EmberAfServiceDiscoveryResult *result) { if (emberAfHaveDiscoveryResponseStatus(result->status)) { MatchDescriptorReq_t *in_dev = GetTopInDeviceDescriptor(); assert(in_dev != NULL); SetInConnEUI64Address((const uint8_t *)result->responseData); emberAfDebugPrint("DEBUG: EUI64 "); emberAfPrintLittleEndianEui64(in_dev->source_eui64); emberAfDebugPrintln(""); SetNextEvent(SC_EZEV_BIND); } emberEventControlSetActive(StateMachineEvent); }
/** @brief Data Received * * This function is called by the Tunneling server plugin whenever data is * received from a client through a tunnel. * * @param tunnelId The identifier of the tunnel through which the data was * received. Ver.: always * @param data Buffer containing the raw octets of the data. Ver.: always * @param dataLen The length in octets of the data. Ver.: always */ void emberAfPluginTunnelingServerDataReceivedCallback(uint16_t tunnelId, uint8_t * data, uint16_t dataLen) { uint8_t tunnelIndex; emberAfDebugPrint("CHF: ServerDataReceived:%x,[", tunnelId); emberAfDebugPrintBuffer(data, dataLen, false); emberAfDebugPrintln("]"); tunnelIndex = findTunnelByTunnelId(tunnelId, SERVER_TUNNEL); if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { emAfPluginCommsHubFunctionTunnelDataReceivedCallback(tunnels[tunnelIndex].remoteDeviceId, dataLen, data); } }
void emAfPluginCommsHubFunctionTunnelCleanup(EmberEUI64 remoteDeviceId) { uint8_t tunnelIndex; tunnelIndex = findTunnelByDeviceId(remoteDeviceId); if (tunnelIndex < EMBER_AF_PLUGIN_COMMS_HUB_FUNCTION_TUNNEL_LIMIT) { emberAfDebugPrint("CHF: TunnelCleanup "); emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId)); emberAfDebugPrintln(""); if (tunnels[tunnelIndex].type == CLIENT_TUNNEL) { emberAfPluginTunnelingClientCleanup(tunnels[tunnelIndex].tunnelId); } else { emberAfPluginTunnelingServerCleanup(tunnels[tunnelIndex].tunnelId); } tunnels[tunnelIndex].state = UNUSED_TUNNEL; } }
// This should be called after CBKE. bool emAfPluginCommsHubFunctionTunnelCreate(EmberEUI64 remoteDeviceId, uint8_t remoteEndpoint) { uint8_t tunnelIndex; emberAfDebugPrint("CHF: TunnelCreate "); emberAfDebugDebugExec(emberAfPrintBigEndianEui64(remoteDeviceId)); emberAfDebugPrintln(" 0x%x", remoteEndpoint); // We only support one tunnel to a given remote device/endpoint so if we // already have a tunnel lets work with it. tunnelIndex = findTunnelByDeviceId(remoteDeviceId); if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { if (tunnels[tunnelIndex].state == CLOSED_TUNNEL) { return requestTunnel(tunnelIndex); } return true; } // Find a slot in the tunnels table for the new tunnel tunnelIndex = findUnusedTunnel(); if (tunnelIndex != EM_AF_PLUGIN_COMMS_HUB_FUNCTION_NULL_TUNNEL_INDEX) { MEMCOPY(tunnels[tunnelIndex].remoteDeviceId, remoteDeviceId, EUI64_SIZE); tunnels[tunnelIndex].remoteNodeId = emberLookupNodeIdByEui64(remoteDeviceId); tunnels[tunnelIndex].remoteEndpoint = remoteEndpoint; tunnels[tunnelIndex].type = CLIENT_TUNNEL; tunnels[tunnelIndex].state = CLOSED_TUNNEL; tunnels[tunnelIndex].tunnelId = 0xFF; tunnels[tunnelIndex].timeoutMSec = 0; return requestTunnel(tunnelIndex); } // This is a misconfiguration or a bug in the code calling this API. Either // the tunnel client plugin limit is set too low for the number of tunnels // required or the code that is calling this function is in error. Either way, // we'll print the error and return false indicating that the tunnel was // not created. emberAfPluginCommsHubFunctionPrintln("%p%p%p", "Error: ", "Tunnel Create failed: ", "Too many tunnels"); return false; }