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));
}
Beispiel #2
0
/*
 * @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++;
    }
}
Beispiel #3
0
/*
 * @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;
}
Beispiel #6
0
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;
}