| | |
| | | #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); |
| | | |
| | | #include "leds.h" |
| | | |
| | | int g_stop = 0; |
| | | |
| | | void sig_handler(int signum) |
| | | { |
| | | switch( signum ) |
| | | { |
| | | case SIGINT: |
| | | case SIGTERM: |
| | | g_stop = 1; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | static inline void msleep(unsigned long ms); |
| | | void sig_handler(int signum); |
| | | |
| | | int main(int argc, char *argv[]) |
| | | { |
| | | int rv; |
| | | leds_t leds = |
| | | { |
| | | .leds = leds_info, |
| | | .count = LEDCNT, |
| | | }; |
| | | |
| | | if( (rv=init_led(&leds)) < 0 ) |
| | | if( (rv=init_led()) < 0 ) |
| | | { |
| | | printf("initial leds gpio failure, rv=%d\n", rv); |
| | | return 1; |
| | |
| | | |
| | | while( !g_stop ) |
| | | { |
| | | turn_led(&leds, LED_R, ON); |
| | | turn_led(LED_R, ON); |
| | | msleep(DELAY); |
| | | turn_led(&leds, LED_R, OFF); |
| | | turn_led(LED_R, OFF); |
| | | msleep(DELAY); |
| | | |
| | | turn_led(&leds, LED_G, ON); |
| | | toggle_led(LED_G); |
| | | msleep(DELAY); |
| | | turn_led(&leds, LED_G, OFF); |
| | | toggle_led(LED_G); |
| | | msleep(DELAY); |
| | | |
| | | turn_led(&leds, LED_B, ON); |
| | | msleep(DELAY); |
| | | turn_led(&leds, LED_B, OFF); |
| | | msleep(DELAY); |
| | | blink_led(LED_B, DELAY); |
| | | } |
| | | |
| | | term_led(&leds); |
| | | term_led(); |
| | | return 0; |
| | | } |
| | | |
| | | int term_led(leds_t *leds) |
| | | |
| | | /*+---------------------------------+ |
| | | *| Leds API based on libgpiod v2.0 | |
| | | *+---------------------------------+*/ |
| | | |
| | | static led_t leds_info[LEDCNT] = |
| | | { |
| | | int i; |
| | | led_t *led; |
| | | {"red", 0, 23, ACTIVE_HIGH, 0, NULL}, /* GPIO1_IO23 on chip0 line 23, active high */ |
| | | {"green", 4, 1, ACTIVE_HIGH, 0, NULL}, /* GPIO5_IO01 on chip4 line 1, active high */ |
| | | {"blue", 4, 8, ACTIVE_HIGH, 0, NULL}, /* GPIO5_IO08 on chip4 line 8, active high */ |
| | | }; |
| | | |
| | | printf("terminate RGB Led gpios\n"); |
| | | /* Leds context */ |
| | | static leds_t leds = |
| | | { |
| | | .leds = leds_info, |
| | | .count = LEDCNT, |
| | | }; |
| | | |
| | | 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) |
| | | int init_led(void) |
| | | { |
| | | led_t *led; |
| | | int i, rv = 0; |
| | |
| | | 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: |
| | | |
| | |
| | | goto cleanup; |
| | | } |
| | | |
| | | for(i=0; i<leds->count; i++) |
| | | for(i=0; i<leds.count; i++) |
| | | { |
| | | led = &leds->leds[i]; |
| | | led = &leds.leds[i]; |
| | | |
| | | snprintf(chip_dev, sizeof(chip_dev), "/dev/gpiochip%d", led->chip_num); |
| | | chip = gpiod_chip_open(chip_dev); |
| | |
| | | cleanup: |
| | | |
| | | if( rv< 0 ) |
| | | term_led(leds); |
| | | term_led(); |
| | | |
| | | if( line_cfg ) |
| | | gpiod_line_config_free(line_cfg); |
| | |
| | | return rv; |
| | | } |
| | | |
| | | int turn_led(leds_t *leds, int which, int cmd) |
| | | int term_led(void) |
| | | { |
| | | int i; |
| | | led_t *led; |
| | | |
| | | printf("terminate RGB Led gpios\n"); |
| | | |
| | | for(i=0; i<leds.count; i++) |
| | | { |
| | | led = &leds.leds[i]; |
| | | |
| | | if( led->request ) |
| | | { |
| | | turn_led(i, OFF); |
| | | gpiod_line_request_release(led->request); |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int turn_led(int which, int cmd) |
| | | { |
| | | led_t *led; |
| | | int rv = 0; |
| | | int value = 0; |
| | | |
| | | if( !leds || which<0 || which>=leds->count ) |
| | | if( which<0 || which>=leds.count ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | led = &leds->leds[which]; |
| | | 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); |
| | | |
| | | led->status = OFF==cmd ? OFF : ON; |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int toggle_led(int which) |
| | | { |
| | | led_t *led; |
| | | |
| | | if( which<0 || which>=leds.count ) |
| | | { |
| | | printf("Invalid input arguments\n"); |
| | | return -1; |
| | | } |
| | | |
| | | led = &leds.leds[which]; |
| | | |
| | | return turn_led(which, !led->status); |
| | | } |
| | | |
| | | void blink_led(int which, int interval) |
| | | { |
| | | led_t *led; |
| | | |
| | | turn_led(which, ON); |
| | | msleep(interval); |
| | | |
| | | turn_led(which, OFF); |
| | | msleep(interval); |
| | | } |
| | | |
| | | /*+-------------------------------+ |
| | | *| Misc functions API | |
| | | *+-------------------------------+*/ |
| | | |
| | | static inline void msleep(unsigned long ms) |
| | | { |
| | |
| | | |
| | | return ; |
| | | } |
| | | |
| | | void sig_handler(int signum) |
| | | { |
| | | switch( signum ) |
| | | { |
| | | case SIGINT: |
| | | case SIGTERM: |
| | | g_stop = 1; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return ; |
| | | } |
| | | |