diff --git a/src/06-mini-project/daemon/gpio/button.c b/src/06-mini-project/daemon/gpio/button.c index 587adf1..25294b3 100644 --- a/src/06-mini-project/daemon/gpio/button.c +++ b/src/06-mini-project/daemon/gpio/button.c @@ -29,9 +29,9 @@ void BTN_add_epoll_event(BTN* btn, int tail); void epoll_init(); static void* epoll_thread(void* arg); -BTN* BTN_init(BTN_type type) { - BTN* btn = malloc(sizeof(BTN)); - if (btn == NULL) return NULL; +int BTN_init(BTN* btn, BTN_type type) { + if (btn == NULL) return -1; + pthread_mutex_init(&btn->mutex, NULL); btn->callback = NULL; @@ -48,15 +48,18 @@ BTN* BTN_init(BTN_type type) { break; default: printf("Invalid button type\n"); - return NULL; + return -1; } strcat(gpio_path, btn->pin); int f = open(GPIO_UNEXPORT, O_WRONLY); - write(f, btn->pin, strlen(btn->pin)); - close(f); + if (f != -1) { + write(f, btn->pin, strlen(btn->pin)); + close(f); + } f = open(GPIO_EXPORT, O_WRONLY); + if (f == -1) return -1; write(f, btn->pin, strlen(btn->pin)); close(f); @@ -65,6 +68,7 @@ BTN* BTN_init(BTN_type type) { strcat(direction_path, "/direction"); f = open(direction_path, O_WRONLY); + if (f == -1) return -1; write(f, "in", 2); close(f); @@ -73,7 +77,8 @@ BTN* BTN_init(BTN_type type) { strcat(edge_path, "/edge"); f = open(edge_path, O_WRONLY); - write(f, "both", 4); // "both" means it triggers on press AND release + if (f == -1) return -1; + write(f, "both", 4); close(f); char value_path[100]; @@ -83,7 +88,7 @@ BTN* BTN_init(BTN_type type) { f = open(value_path, O_RDONLY); if (f == -1) { printf("Failed to setup button on pin %s\n", btn->pin); - return NULL; + return -1; } btn->fd = f; @@ -96,7 +101,8 @@ BTN* BTN_init(BTN_type type) { if (tail >= MAX_BTN) { pthread_mutex_unlock(&btn_list_mutex); perror("Failed to add epoll event"); - exit(EXIT_FAILURE); + close(btn->fd); + return -1; } btn_list[tail] = btn; @@ -106,7 +112,18 @@ BTN* BTN_init(BTN_type type) { BTN_add_epoll_event(btn, tail); pthread_mutex_unlock(&btn_list_mutex); - return btn; + return 0; +} + +void BTN_deinit(BTN* btn) { + if (btn == NULL) return; + pthread_mutex_lock(&btn->mutex); + if (btn->fd != -1) { + close(btn->fd); + btn->fd = -1; + } + pthread_mutex_unlock(&btn->mutex); + pthread_mutex_destroy(&btn->mutex); } void BTN_set_callback(BTN* btn, BTN_callback callback) { @@ -121,7 +138,7 @@ void BTN_add_epoll_event(BTN* btn, int tail) { // EPOLLERR is used to detect if there is an error // EPOLLET is for edge triggered mode (non-blocking) ev[tail].events = EPOLLIN | EPOLLERR | EPOLLET; - ev[tail].data.fd = btn->fd; + ev[tail].data.ptr = btn; int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, btn->fd, &ev[tail]); if (ret < 0) { @@ -154,28 +171,19 @@ static void* epoll_thread(void* arg) { } for (int i = 0; i < n; i++) { char buf[2]; - int fd = events[i].data.fd; - int tail = -1; - BTN* btn = NULL; - for (int j = 0; j < MAX_BTN; j++) { - if (btn_list[j] == NULL) continue; - if (btn_list[j]->fd == fd) { - tail = j; - btn = btn_list[j]; - break; - } - } - if (tail == -1) { - printf("No button found for fd %d\n", fd); - continue; - } - pread(btn->fd, buf, sizeof(buf), 0); - if (buf[0] == '1') { - // printf("Button %s pressed\n", btn->pin); - if (btn->callback != NULL) { - btn->callback(); + BTN* btn = (BTN*)events[i].data.ptr; + if (btn == NULL) continue; + + pthread_mutex_lock(&btn->mutex); + if (btn->fd != -1) { + pread(btn->fd, buf, sizeof(buf), 0); + if (buf[0] == '1') { + if (btn->callback != NULL) { + btn->callback(); + } } } + pthread_mutex_unlock(&btn->mutex); } } return NULL; diff --git a/src/06-mini-project/daemon/gpio/button.h b/src/06-mini-project/daemon/gpio/button.h index 6778b42..cb3ec16 100644 --- a/src/06-mini-project/daemon/gpio/button.h +++ b/src/06-mini-project/daemon/gpio/button.h @@ -22,7 +22,8 @@ typedef struct { pthread_mutex_t mutex; } BTN; -BTN* BTN_init(BTN_type type); +int BTN_init(BTN* btn, BTN_type type); +void BTN_deinit(BTN* btn); void BTN_set_callback(BTN* btn, BTN_callback callback); #endif diff --git a/src/06-mini-project/daemon/gpio/led.c b/src/06-mini-project/daemon/gpio/led.c index 7b797eb..a866aa9 100644 --- a/src/06-mini-project/daemon/gpio/led.c +++ b/src/06-mini-project/daemon/gpio/led.c @@ -16,9 +16,8 @@ #include -LED* LED_init(LED_type type) { - LED* led = malloc(sizeof(LED)); - if (led == NULL) return NULL; +int LED_init(LED* led, LED_type type) { + if (led == NULL) return -1; // Concatenate GPIO LED path based on type char gpio_path[32] = GPIO_LED_BASE; @@ -32,7 +31,7 @@ LED* LED_init(LED_type type) { break; default: printf("Invalid LED type\n"); - return NULL; + return -1; } strcat(gpio_path, pin); @@ -63,15 +62,15 @@ LED* LED_init(LED_type type) { f = open(value_path, O_RDWR); if (f == -1) { printf("Failed to setup led on pin %s\n", pin); - return NULL; + return -1; } led->gpio = f; if (pthread_mutex_init(&led->mutex, NULL) != 0) { close(f); - return NULL; + return -1; } - return led; + return 0; } void LED_on(LED* led) { @@ -100,8 +99,17 @@ void LED_toggle(LED* led) { char value[2]; pread(led->gpio, value, sizeof(value), 0); if (value[0] == '0') { - LED_on(led); + pwrite(led->gpio, "1", sizeof("1"), 0); } else { - LED_off(led); + pwrite(led->gpio, "0", sizeof("0"), 0); } + pthread_mutex_unlock(&led->mutex); +} + +void LED_deinit(LED* led) { + if (led == NULL) { + return; + } + pthread_mutex_destroy(&led->mutex); + close(led->gpio); } diff --git a/src/06-mini-project/daemon/gpio/led.h b/src/06-mini-project/daemon/gpio/led.h index 9f31acd..6cabc34 100644 --- a/src/06-mini-project/daemon/gpio/led.h +++ b/src/06-mini-project/daemon/gpio/led.h @@ -16,9 +16,10 @@ typedef struct { pthread_mutex_t mutex; } LED; -LED* LED_init(LED_type type); +int LED_init(LED* led, LED_type type); void LED_on(LED* led); void LED_off(LED* led); void LED_toggle(LED* led); +void LED_deinit(LED* led); #endif //LED_H diff --git a/src/06-mini-project/daemon/main.c b/src/06-mini-project/daemon/main.c index 44d052c..89e2b30 100644 --- a/src/06-mini-project/daemon/main.c +++ b/src/06-mini-project/daemon/main.c @@ -21,17 +21,30 @@ int main(void) { + BTN btn_inc, btn_dec, btn_mode; + if (BTN_init(&btn_inc, BTN_INCREASE) != 0) { + fprintf(stderr, "Failed to initialize increase button\n"); + return 1; + } + if (BTN_init(&btn_dec, BTN_DECREASE) != 0) { + fprintf(stderr, "Failed to initialize decrease button\n"); + return 1; + } + if (BTN_init(&btn_mode, BTN_MODE) != 0) { + fprintf(stderr, "Failed to initialize mode button\n"); + return 1; + } - BTN* btn_inc = BTN_init(BTN_INCREASE); - BTN* btn_dec = BTN_init(BTN_DECREASE); - BTN* btn_mode = BTN_init(BTN_MODE); + LED led_power; + if (LED_init(&led_power, LED_POWER) != 0) { + fprintf(stderr, "Failed to initialize power LED\n"); + return 1; + } - LED* led_power = LED_init(LED_POWER); - - BTN_set_callback(btn_inc, btn_increase_period); - BTN_set_callback(btn_dec, btn_decrease_period); - BTN_set_callback(btn_mode, mode_toggle); + BTN_set_callback(&btn_inc, btn_increase_period); + BTN_set_callback(&btn_dec, btn_decrease_period); + BTN_set_callback(&btn_mode, mode_toggle); struct ipc_callbacks_t ipc_cbs = { .on_dec_period = decrease_period, @@ -54,7 +67,7 @@ int main(void) { init_oled(&oled_cbs); - btn_set_led(led_power); + btn_set_led(&led_power); init_animations(); while (1) { @@ -62,5 +75,9 @@ int main(void) { } stop_ipc_server(); + LED_deinit(&led_power); + BTN_deinit(&btn_inc); + BTN_deinit(&btn_dec); + BTN_deinit(&btn_mode); return 0; }