TEST_F(RDMUtilTest, testRequiresAction) { EXPECT_TRUE(RDMUtil_RequiresAction(OUR_UID, OUR_UID)); EXPECT_TRUE(RDMUtil_RequiresAction(OUR_UID, VENDORCAST_UID)); EXPECT_TRUE(RDMUtil_RequiresAction(OUR_UID, BROADCAST_UID)); EXPECT_FALSE(RDMUtil_RequiresAction(OUR_UID, OTHER_VENDORCAST_UID)); EXPECT_FALSE(RDMUtil_RequiresAction(OUR_UID, OTHER_UID)); }
/* * @brief Increment the bad-checksum counter if the frame was for us. */ static inline void PossiblyIncrementChecksumCounter(const uint8_t *frame) { uint8_t uid[UID_LENGTH]; RDMHandler_GetUID(uid); RDMHeader *header = (RDMHeader*) frame; if (RDMUtil_RequiresAction(uid, header->dest_uid)) { SysLog_Message(SYSLOG_ERROR, "Checksum mismatch"); g_responder_counters.rdm_checksum_invalid++; } }
/* * @brief Increment the length-mismatch counter if the frame was for us. */ static inline void PossiblyIncrementLengthMismatchCounter( const uint8_t *frame) { uint8_t uid[UID_LENGTH]; RDMHandler_GetUID(uid); RDMHeader *header = (RDMHeader*) frame; if (RDMUtil_RequiresAction(uid, header->dest_uid)) { g_responder_counters.rdm_length_mismatch++; } }
static int GetSetModelId(const RDMHeader *header, const uint8_t *param_data) { uint8_t our_uid[UID_LENGTH]; RDMHandler_GetUID(our_uid); if (!RDMUtil_RequiresAction(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } uint16_t sub_device = ntohs(header->sub_device); // No subdevice support for now. if (sub_device != SUBDEVICE_ROOT && sub_device != SUBDEVICE_ALL) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } else if (sub_device == SUBDEVICE_ALL && header->command_class == GET_COMMAND) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } if (header->command_class == GET_COMMAND) { if (header->param_data_length) { return RDMResponder_BuildNack(header, NR_FORMAT_ERROR); } if (RDMUtil_UIDCompare(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } uint16_t model_id = NULL_MODEL_ID; if (g_rdm_handler.active_model) { model_id = g_rdm_handler.active_model->model_id; } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, model_id); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); } else if (header->command_class == SET_COMMAND) { if (header->param_data_length != sizeof(uint16_t)) { return RDMResponder_BuildNack(header, NR_FORMAT_ERROR); } // take action uint16_t new_model = JoinShort(param_data[0], param_data[1]); bool ok = RDMHandler_SetActiveModel(new_model); if (RDMUtil_UIDCompare(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } if (!ok) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } return RDMResponder_BuildSetAck(header); } return RDM_RESPONDER_NO_RESPONSE; }
static int ProxyModel_HandleRequest(const RDMHeader *header, const uint8_t *param_data) { int response_size = 0; // The proxy always gets first dibs on responding. if (RDMUtil_RequiresAction(g_responder->uid, header->dest_uid)) { response_size = HandleRequest(header, param_data); if (response_size) { return response_size; } } unsigned int i = 0u; for (; i < NUMBER_OF_CHILDREN; i++) { if (RDMUtil_RequiresAction(g_children[i].responder.uid, header->dest_uid)) { RDMResponder_SwitchResponder(&g_children[i].responder); int response_size = HandleChildRequest(header, param_data, i); RDMResponder_RestoreResponder(); if (response_size) { return response_size; } } } return RDM_RESPONDER_NO_RESPONSE; }
static int MovingLightModel_HandleRequest(const RDMHeader *header, const uint8_t *param_data) { if (!RDMUtil_RequiresAction(g_responder->uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } if (header->command_class == DISCOVERY_COMMAND) { return RDMResponder_HandleDiscovery(header, param_data); } uint16_t sub_device = ntohs(header->sub_device); // No subdevices. if (sub_device != SUBDEVICE_ROOT && sub_device != SUBDEVICE_ALL) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } // This model has no sub devices. if (header->command_class == GET_COMMAND && sub_device == SUBDEVICE_ALL) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } return RDMResponder_DispatchPID(header, param_data); }
static int DimmerModel_HandleRequest(const RDMHeader *header, const uint8_t *param_data) { if (!RDMUtil_RequiresAction(g_responder->uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } // The standard isn't at all clear how a responder is supposed to behave if // it receives discovery commands with a non-0 subdevice. For now we just // ignore the sub-device field. if (header->command_class == DISCOVERY_COMMAND) { return RDMResponder_HandleDiscovery(header, param_data); } const uint16_t sub_device = ntohs(header->sub_device); // GETs to all subdevices are invalid. if (header->command_class == GET_COMMAND && sub_device == SUBDEVICE_ALL) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } // Check if we're locked bool locked = false; if (header->command_class == SET_COMMAND) { if (g_root_device.lock_state == LOCK_STATE_ALL_LOCKED || (g_root_device.lock_state == LOCK_STATE_SUBDEVICES_LOCKED && sub_device != SUBDEVICE_ROOT)) { locked = true; } } if (sub_device == SUBDEVICE_ROOT) { if (locked) { return RDMResponder_BuildNack(header, NR_WRITE_PROTECT); } else { return RDMResponder_DispatchPID(header, param_data); } } unsigned int i = 0u; bool handled = false; int response_size = RDM_RESPONDER_NO_RESPONSE; for (; i < NUMBER_OF_SUB_DEVICES; i++) { if (sub_device == g_subdevices[i].index || sub_device == SUBDEVICE_ALL) { if (!locked) { g_active_device = &g_subdevices[i]; RDMResponder_SwitchResponder(&g_subdevices[i].responder); response_size = RDMResponder_DispatchPID(header, param_data); } handled = true; } } RDMResponder_RestoreResponder(); if (!handled) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } if (locked) { return RDMResponder_BuildNack(header, NR_WRITE_PROTECT); } // If it was an all-subdevices call, it's not really clear how to handle the // response, in this case we return the last one. return response_size; }