blob: 4ca2d5a40307774dc512c4c3df37b42f86b22b92 [file] [log] [blame]
/*
* Copyright (c) 2020 Seagate Technology LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/drivers/led.h>
#define BRIGHTNESS_MAX 100
#define TEST_MAX_COLORS 8
#define COLOR_FULL 0xff
#define _COLOR_MAPPING(led_node_id) \
const uint8_t test_color_mapping_##led_node_id[] = \
DT_PROP(led_node_id, color_mapping)
#define COLOR_MAPPING(led_node_id) \
IF_ENABLED(DT_NODE_HAS_PROP(led_node_id, color_mapping), \
(_COLOR_MAPPING(led_node_id);))
#define LED_INFO_COLOR(led_node_id) \
{ \
.label = DT_PROP(led_node_id, label), \
.index = DT_PROP_OR(led_node_id, index, 0), \
.num_colors = \
DT_PROP_LEN(led_node_id, color_mapping), \
.color_mapping = test_color_mapping_##led_node_id, \
},
#define LED_INFO_NO_COLOR(led_node_id) \
{ \
.label = DT_PROP(led_node_id, label), \
.index = DT_PROP_OR(led_node_id, index, 0), \
.num_colors = 0, \
.color_mapping = NULL, \
},
#define LED_INFO(led_node_id) \
COND_CODE_1(DT_NODE_HAS_PROP(led_node_id, color_mapping), \
(LED_INFO_COLOR(led_node_id)), \
(LED_INFO_NO_COLOR(led_node_id)))
#define LED_CONTROLLER_INFO(node_id) \
\
DT_FOREACH_CHILD(node_id, COLOR_MAPPING) \
\
const struct led_info test_led_info[] = { \
DT_FOREACH_CHILD(node_id, LED_INFO) \
}; \
\
static ZTEST_DMEM int num_leds = ARRAY_SIZE(test_led_info)
LED_CONTROLLER_INFO(DT_ALIAS(led_controller_0));
static ZTEST_BMEM const struct device *const led_ctrl = DEVICE_DT_GET(DT_ALIAS(led_controller_0));
static void test_led_setup(void)
{
zassert_true(device_is_ready(led_ctrl), "LED controller is not ready");
zassert_not_equal(num_leds, 0, "No LEDs subnodes found in DT for controller");
k_object_access_grant(led_ctrl, k_current_get());
}
ZTEST_USER(led_user, test_led_get_info)
{
uint8_t led;
int ret;
if (!led_ctrl || !num_leds) {
ztest_test_skip();
}
for (led = 0; led < num_leds; led++) {
const struct led_info *info;
uint8_t col;
ret = led_get_info(led_ctrl, led, &info);
if (ret == -ENOTSUP) {
TC_PRINT("led_get_info() syscall is not supported.\n");
ztest_test_skip();
return;
}
zassert_equal(ret, 0, "LED %d - led_get_info() error (ret=%d)",
led, ret);
zassert_true(!strcmp(info->label, test_led_info[led].label),
"LED %d - label: %s instead of %s",
led, info->label, test_led_info[led].label);
zassert_equal(info->index, test_led_info[led].index,
"LED %d - index: %d instead of %d", led,
info->index, test_led_info[led].index);
zassert_equal(info->num_colors, test_led_info[led].num_colors,
"LED %d - num_colors: %d instead of %d", led,
info->num_colors, test_led_info[led].num_colors);
TC_PRINT("LED %d - label: %s, index: %d, num_colors: %d",
led, info->label, info->index, info->num_colors);
if (!info->num_colors) {
continue;
}
TC_PRINT(" color_mapping: ");
for (col = 0; col < info->num_colors; col++) {
zassert_equal(info->color_mapping[col],
test_led_info[led].color_mapping[col],
"LED %d - color_mapping[%d]=%d instead of %d",
led, col, info->color_mapping[col],
test_led_info[led].color_mapping[col]);
TC_PRINT("%d", info->color_mapping[col]);
}
TC_PRINT("\n");
}
}
ZTEST_USER(led_user, test_led_on)
{
uint8_t led;
int ret;
if (!led_ctrl || !num_leds) {
ztest_test_skip();
}
for (led = 0; led < num_leds; led++) {
ret = led_on(led_ctrl, led);
zassert_equal(ret, 0, "LED %d - failed to turn on", led);
}
}
ZTEST_USER(led_user, test_led_off)
{
uint8_t led;
int ret;
if (!led_ctrl || !num_leds) {
ztest_test_skip();
}
for (led = 0; led < num_leds; led++) {
ret = led_off(led_ctrl, led);
zassert_equal(ret, 0, "LED %d - failed to turn off", led);
}
}
ZTEST_USER(led_user, test_led_set_color)
{
uint8_t led;
uint8_t colors[TEST_MAX_COLORS + 1];
int ret;
if (!led_ctrl || !num_leds) {
ztest_test_skip();
}
for (led = 0; led < num_leds; led++) {
uint8_t num_colors = test_led_info[led].num_colors;
uint8_t col;
if (num_colors > TEST_MAX_COLORS) {
TC_PRINT("LED %d - skip set_color test, num_colors: %d"
" (test limit is %d)",
led, num_colors, TEST_MAX_COLORS);
continue;
}
memset(colors, 0, sizeof(colors));
/* Try to set more colors than supported. */
ret = led_set_color(led_ctrl, led, num_colors + 1, colors);
zassert_not_equal(ret, 0, "LED %d - setting %d"
" colors should fail (%d supported)",
led, num_colors + 1, num_colors);
if (!num_colors) {
continue;
}
/* Try to set less colors than supported. */
ret = led_set_color(led_ctrl, led, num_colors - 1, colors);
zassert_not_equal(ret, 0, "LED %d - setting %d"
" colors should fail (%d supported)",
led, num_colors - 1, num_colors);
/* Ensure the LED is on to get a visual feedback. */
led_set_brightness(led_ctrl, led, BRIGHTNESS_MAX / 2);
/* Set each color gradually to its maximum level. */
for (col = 0; col < num_colors; col++) {
uint16_t level;
memset(colors, 0, sizeof(colors));
for (level = 0; level <= COLOR_FULL; level++) {
colors[col] = level;
ret = led_set_color(led_ctrl, led,
num_colors, colors);
zassert_equal(ret, 0,
"LED %d - failed to set color[%d] to %d",
led, level);
}
}
}
}
ZTEST_USER(led_user, test_led_set_brightness)
{
uint8_t led;
int ret;
if (!led_ctrl || !num_leds) {
ztest_test_skip();
}
for (led = 0; led < num_leds; led++) {
uint16_t level;
for (level = 0; level <= BRIGHTNESS_MAX; level++) {
ret = led_set_brightness(led_ctrl, led, level);
zassert_equal(ret, 0,
"LED %d - failed to set brightness to %d",
led, level);
}
for (level = BRIGHTNESS_MAX + 1; level <= 255; level++) {
ret = led_set_brightness(led_ctrl, led, level);
zassert_not_equal(ret, 0,
"LED %d - setting brightness to %d"
" should fail (maximum: %d)",
led, level, BRIGHTNESS_MAX);
}
}
}
void *led_setup(void)
{
test_led_setup();
return NULL;
}
ZTEST_SUITE(led_user, NULL, led_setup, NULL, NULL, NULL);