From 1e563e2b731d928942f43e1341c8c50b0faf1c01 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Fri, 31 May 2024 11:39:31 +0800
Subject: [PATCH]  APPS:IGKBoard-IMX6ULL: Add test-apps source code:

---
 drivers/test-apps/leds.c |  332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 332 insertions(+), 0 deletions(-)

diff --git a/drivers/test-apps/leds.c b/drivers/test-apps/leds.c
new file mode 100644
index 0000000..1918a0b
--- /dev/null
+++ b/drivers/test-apps/leds.c
@@ -0,0 +1,332 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2024 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  led.c
+ *    Description:  This file is used to control RGB 3-colors LED
+ *
+ *
+ * Pin connection:
+ *               RGB Led Module           IGKBoard
+ *                   R        <----->      #Pin33
+ *                   G        <----->      #Pin35
+ *                   B        <----->      #Pin37
+ *                  GND       <----->      GND
+ *
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <gpiod.h>
+
+#define DELAY     300
+
+#define ON        1
+#define OFF       0
+
+/* Three LEDs number */
+enum
+{
+    LED_R = 0,
+    LED_G,
+    LED_B,
+    LEDCNT,
+};
+
+enum
+{
+    ACTIVE_HIGH, /* High level will turn led on */
+    ACTIVE_LOW,  /* Low level will turn led on */
+};
+
+/* Three LEDs hardware information */
+typedef struct led_s
+{
+    const char               *name;      /* RGB 3-color LED name  */
+    int                       chip_num;  /* RGB 3-color LED connect chip */
+    int                       gpio_num;  /* RGB 3-color LED connect line */
+    int                       active;    /* RGB 3-color LED active level */
+    struct gpiod_line_request *request;  /* libgpiod gpio request handler */
+} led_t;
+
+static led_t leds_info[LEDCNT] =
+{
+    {"red",   0, 23, ACTIVE_HIGH, NULL }, /* GPIO1_IO23 on chip0 line 23, active high */
+    {"green", 4, 1,  ACTIVE_HIGH, NULL }, /* GPIO5_IO01 on chip4 line 1, active high */
+    {"blue",  4, 8,  ACTIVE_HIGH, NULL }, /* GPIO5_IO08 on chip4 line 8, active high */
+};
+
+/* Three LEDs API context */
+typedef struct leds_s
+{
+    led_t               *leds;  /* led pointer to leds_info */
+    int                  count; /* led count */
+} leds_t;
+
+
+/* function declaration  */
+int init_led(leds_t *leds);
+int term_led(leds_t *leds);
+int turn_led(leds_t *leds, int which, int cmd);
+static inline void msleep(unsigned long ms);
+
+
+int g_stop = 0;
+
+void sig_handler(int signum)
+{
+    switch( signum )
+    {
+        case SIGINT:
+        case SIGTERM:
+            g_stop = 1;
+
+        default:
+            break;
+    }
+
+    return ;
+}
+
+int main(int argc, char *argv[])
+{
+    int                 rv;
+    leds_t              leds =
+    {
+        .leds  = leds_info,
+        .count = LEDCNT,
+    };
+
+    if( (rv=init_led(&leds)) < 0 )
+    {
+        printf("initial leds gpio failure, rv=%d\n", rv);
+        return 1;
+    }
+    printf("initial RGB Led gpios okay\n");
+
+    signal(SIGINT,  sig_handler);
+    signal(SIGTERM, sig_handler);
+
+    while( !g_stop )
+    {
+        turn_led(&leds, LED_R, ON);
+        msleep(DELAY);
+        turn_led(&leds, LED_R, OFF);
+        msleep(DELAY);
+
+        turn_led(&leds, LED_G, ON);
+        msleep(DELAY);
+        turn_led(&leds, LED_G, OFF);
+        msleep(DELAY);
+
+        turn_led(&leds, LED_B, ON);
+        msleep(DELAY);
+        turn_led(&leds, LED_B, OFF);
+        msleep(DELAY);
+    }
+
+    term_led(&leds);
+    return 0;
+}
+
+int term_led(leds_t *leds)
+{
+    int            i;
+    led_t         *led;
+
+    printf("terminate RGB Led gpios\n");
+
+    if( !leds )
+    {
+        printf("Invalid input arguments\n");
+        return -1;
+    }
+
+    for(i=0; i<leds->count; i++)
+    {
+        led = &leds->leds[i];
+
+        if( led->request )
+        {
+            turn_led(leds, i, OFF);
+            gpiod_line_request_release(led->request);
+        }
+    }
+
+    return 0;
+}
+
+
+int init_led(leds_t *leds)
+{
+    led_t                       *led;
+    int                          i, rv = 0;
+    char                         chip_dev[32];
+    struct gpiod_chip           *chip;      /* gpio chip */
+    struct gpiod_line_settings  *settings;  /* gpio direction, bias, active_low, value */
+    struct gpiod_line_config    *line_cfg;  /* gpio line */
+    struct gpiod_request_config *req_cfg;   /* gpio consumer, it can be NULL */
+
+
+    if( !leds )
+    {
+        printf("Invalid input arguments\n");
+        return -1;
+    }
+
+
+    /* defined in libgpiod-2.0/lib/line-settings.c:
+
+        struct gpiod_line_settings {
+            enum gpiod_line_direction direction;
+            enum gpiod_line_edge edge_detection;
+            enum gpiod_line_drive drive;
+            enum gpiod_line_bias bias;
+            bool active_low;
+            enum gpiod_line_clock event_clock;
+            long debounce_period_us;
+            enum gpiod_line_value output_value;
+        };
+     */
+    settings = gpiod_line_settings_new();
+    if (!settings)
+    {
+        printf("unable to allocate line settings\n");
+        rv = -2;
+        goto cleanup;
+    }
+
+    /* defined in libgpiod-2.0/lib/line-config.c
+
+        struct gpiod_line_config {
+            struct per_line_config line_configs[LINES_MAX];
+            size_t num_configs;
+            enum gpiod_line_value output_values[LINES_MAX];
+            size_t num_output_values;
+            struct settings_node *sref_list;
+        };
+    */
+
+    line_cfg = gpiod_line_config_new();
+    if (!line_cfg)
+    {
+        printf("unable to allocate the line config structure");
+        rv = -2;
+        goto cleanup;
+    }
+
+
+    /* defined in libgpiod-2.0/lib/request-config.c:
+
+        struct gpiod_request_config {
+            char consumer[GPIO_MAX_NAME_SIZE];
+            size_t event_buffer_size;
+        };
+     */
+    req_cfg = gpiod_request_config_new();
+    if (!req_cfg)
+    {
+        printf("unable to allocate the request config structure");
+        rv = -2;
+        goto cleanup;
+    }
+
+    for(i=0; i<leds->count; i++)
+    {
+        led = &leds->leds[i];
+
+        snprintf(chip_dev, sizeof(chip_dev), "/dev/gpiochip%d", led->chip_num);
+        chip = gpiod_chip_open(chip_dev);
+        if( !chip )
+        {
+            printf("open gpiochip failure, maybe you need running as root\n");
+            rv = -3;
+            goto cleanup;
+        }
+
+        /* Set as output direction, active low and default level as inactive */
+        gpiod_line_settings_reset(settings);
+        gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
+        gpiod_line_settings_set_active_low(settings, led->active);
+        gpiod_line_settings_set_output_value(settings, GPIOD_LINE_VALUE_INACTIVE);
+
+        /* set gpio line */
+        gpiod_line_config_reset(line_cfg);
+        gpiod_line_config_add_line_settings(line_cfg, &led->gpio_num, 1, settings);
+
+        /* Can be NULL for default settings. */
+        gpiod_request_config_set_consumer(req_cfg, led->name);
+
+        /* Request a set of lines for exclusive usage. */
+        led->request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
+
+        gpiod_chip_close(chip);
+        //printf("request %5s led[%d] for gpio output okay\n", led->name, led->gpio);
+    }
+
+cleanup:
+
+    if( rv< 0 )
+        term_led(leds);
+
+    if( line_cfg )
+        gpiod_line_config_free(line_cfg);
+
+    if( req_cfg )
+        gpiod_request_config_free(req_cfg);
+
+    if( settings )
+        gpiod_line_settings_free(settings);
+
+    return rv;
+}
+
+int turn_led(leds_t *leds, int which, int cmd)
+{
+    led_t         *led;
+    int            rv = 0;
+    int            value = 0;
+
+    if( !leds || which<0 || which>=leds->count )
+    {
+        printf("Invalid input arguments\n");
+        return -1;
+    }
+
+    led = &leds->leds[which];
+
+    value = OFF==cmd ? GPIOD_LINE_VALUE_INACTIVE : GPIOD_LINE_VALUE_ACTIVE;
+
+    gpiod_line_request_set_value(led->request, led->gpio_num, value);
+
+    return 0;
+}
+
+static inline void msleep(unsigned long ms)
+{
+    struct timespec cSleep;
+    unsigned long ulTmp;
+
+    cSleep.tv_sec = ms / 1000;
+    if (cSleep.tv_sec == 0)
+    {
+        ulTmp = ms * 10000;
+        cSleep.tv_nsec = ulTmp * 100;
+    }
+    else
+    {
+        cSleep.tv_nsec = 0;
+    }
+
+    nanosleep(&cSleep, 0);
+
+    return ;
+}

--
Gitblit v1.9.1