diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..f16c844 --- /dev/null +++ b/src/config.c @@ -0,0 +1,70 @@ +#include +#include "config.h" +#include "log.h" + +#define EXITFUNCBLOCK_FUNCCOUNT 64 + +typedef struct tagEXITFUNCBLOCK +{ + struct tagEXITFUNCBLOCK *next; + int num_funcs; + PEXITFUNC funcs[EXITFUNCBLOCK_FUNCCOUNT]; +} EXITFUNCBLOCK, *PEXITFUNCBLOCK; + +/* The global configuration data */ +GLOBAL_CONFIG Gconfig; + +static PEXITFUNCBLOCK exitfuncs = NULL; + +static void run_exit_funcs(void) +{ + int i; + PEXITFUNCBLOCK p; + + while (exitfuncs) + { + p = exitfuncs; + exitfuncs = p->next; + for (i = p->num_funcs - 1; i >= 0; i++) + (*(p->funcs[i]))(); + free(p); + } +} + +static void init_defaults(void) +{ + Gconfig.framebuffer_device = "/dev/fb1"; + Gconfig.button_debounce = 100; + Gconfig.sys_mq_length = 64; +} + +HRESULT Config_setup(void) +{ + if (atexit(run_exit_funcs)) + { + Log(LFATAL, "Unable to set up exit function mechanism"); + return E_FAIL; + } + init_defaults(); + return S_OK; +} + +HRESULT Config_exitfunc(PEXITFUNC pfn) +{ + PEXITFUNCBLOCK p; + + if (!exitfuncs || (exitfuncs->num_funcs == EXITFUNCBLOCK_FUNCCOUNT)) + { + p = (PEXITFUNCBLOCK)malloc(sizeof(EXITFUNCBLOCK)); + if (!p) + { + Log(LERROR, "unable to allocate another exit function block"); + return E_OUTOFMEMORY; + } + p->next = exitfuncs; + p->num_funcs = 0; + exitfuncs = p; + } + exitfuncs->funcs[exitfuncs->num_funcs++] = pfn; + return S_OK; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..b716af5 --- /dev/null +++ b/src/config.h @@ -0,0 +1,19 @@ +#ifndef __CONFIG_H_INCLUDED +#define __CONFIG_H_INCLUDED + +#include "wintype.h" + +typedef void (*PEXITFUNC)(void); + +typedef struct tagGLOBAL_CONFIG { + PCSTR framebuffer_device; + UINT32 button_debounce; + UINT32 sys_mq_length; +} GLOBAL_CONFIG; + +extern GLOBAL_CONFIG Gconfig; + +extern HRESULT Config_setup(void); +extern HRESULT Config_exitfunc(PEXITFUNC pfn); + +#endif /* __CONFIG_H_INCLUDED */ diff --git a/src/fbinit.c b/src/fbinit.c index f6664dc..24cbe7e 100644 --- a/src/fbinit.c +++ b/src/fbinit.c @@ -6,6 +6,7 @@ #include #include #include +#include "config.h" #include "log.h" #include "fbinit.h" #include "scode.h" @@ -27,13 +28,25 @@ inline static UINT16 makemask(unsigned offset, unsigned length) return (UINT16)(((1 << length) - 1) << offset); } +static void do_cleanup(void) +{ + /* additional cleanup here */ + + memset(Fb_Ptr, 0, local_info.screenbytes); + munmap((void *)Fb_Ptr, local_info.screenbytes); + Fb_Ptr = NULL; + + close(fb_fd); + fb_fd = -1; +} + HRESULT Fb_setup(void) { HRESULT hr = S_OK; struct fb_fix_screeninfo fixed; struct fb_var_screeninfo var; - fb_fd = open("/dev/fb1", O_RDWR); + fb_fd = open(Gconfig.framebuffer_device, O_RDWR); if (fb_fd == -1) { hr = ERRNO_AS_SCODE; @@ -89,21 +102,12 @@ HRESULT Fb_setup(void) /* additional setup here */ + hr = Config_exitfunc(do_cleanup); + if (FAILED(hr)) + do_cleanup(); return hr; } -void Fb_cleanup(void) -{ - /* additional cleanup here */ - - memset(Fb_Ptr, 0, local_info.screenbytes); - munmap((void *)Fb_Ptr, local_info.screenbytes); - Fb_Ptr = NULL; - - close(fb_fd); - fb_fd = -1; -} - void Fb_clear(void) { memset(Fb_Ptr, 0, local_info.screenbytes); diff --git a/src/fbinit.h b/src/fbinit.h index 11f4d8b..8638317 100644 --- a/src/fbinit.h +++ b/src/fbinit.h @@ -27,7 +27,6 @@ extern PCFBINFO Fb_Info; extern UINT16 *Fb_Ptr; extern HRESULT Fb_setup(void); -extern void Fb_cleanup(void); extern void Fb_clear(void); #endif /* __FBINIT_H_INCLUDED */ diff --git a/src/gpio.c b/src/gpio.c index 13255e9..b4e8758 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -1,5 +1,6 @@ #include #include +#include "config.h" #include "log.h" #include "scode.h" #include "gpio.h" @@ -12,8 +13,31 @@ #define PWM_BACKLIGHT 0 +static void do_cleanup(void) +{ + /* close down the backlight lines */ + bcm2835_pwm_set_mode(PWM_BACKLIGHT, 1, 0); + bcm2835_gpio_set_pud(GLINE_BACKLIGHT, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BACKLIGHT, BCM2835_GPIO_FSEL_INPT); + + /* close down the button lines */ + bcm2835_gpio_set_pud(GLINE_BUTTON1, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON1, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON2, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON2, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON3, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON3, BCM2835_GPIO_FSEL_INPT); + bcm2835_gpio_set_pud(GLINE_BUTTON4, BCM2835_GPIO_PUD_OFF); + bcm2835_gpio_fsel(GLINE_BUTTON4, BCM2835_GPIO_FSEL_INPT); + + if (!bcm2835_close()) + Log(LWARN, "Closing BCM2835 library failed"); +} + HRESULT Gpio_setup(void) { + HRESULT hr; + if (!bcm2835_init()) { Log(LFATAL, "Error initializing BCM2835 library"); @@ -38,28 +62,10 @@ HRESULT Gpio_setup(void) bcm2835_pwm_set_range(PWM_BACKLIGHT, GSB_BACKLIGHT_MAX + 1); bcm2835_pwm_set_data(PWM_BACKLIGHT, GSB_BACKLIGHT_MAX); - return S_OK; -} - -void Gpio_cleanup(void) -{ - /* close down the backlight lines */ - bcm2835_pwm_set_mode(PWM_BACKLIGHT, 1, 0); - bcm2835_gpio_set_pud(GLINE_BACKLIGHT, BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_fsel(GLINE_BACKLIGHT, BCM2835_GPIO_FSEL_INPT); - - /* close down the button lines */ - bcm2835_gpio_set_pud(GLINE_BUTTON1, BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_fsel(GLINE_BUTTON1, BCM2835_GPIO_FSEL_INPT); - bcm2835_gpio_set_pud(GLINE_BUTTON2, BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_fsel(GLINE_BUTTON2, BCM2835_GPIO_FSEL_INPT); - bcm2835_gpio_set_pud(GLINE_BUTTON3, BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_fsel(GLINE_BUTTON3, BCM2835_GPIO_FSEL_INPT); - bcm2835_gpio_set_pud(GLINE_BUTTON4, BCM2835_GPIO_PUD_OFF); - bcm2835_gpio_fsel(GLINE_BUTTON4, BCM2835_GPIO_FSEL_INPT); - - if (!bcm2835_close()) - Log(LWARN, "Closing BCM2835 library failed"); + hr = Config_exitfunc(do_cleanup); + if (FAILED(hr)) + do_cleanup(); + return hr; } UINT32 Gpio_read_buttons(void) diff --git a/src/gpio.h b/src/gpio.h index 38d5555..24c7398 100644 --- a/src/gpio.h +++ b/src/gpio.h @@ -13,7 +13,6 @@ #define GSB_BACKLIGHT_MAX 1023 extern HRESULT Gpio_setup(void); -extern void Gpio_cleanup(void); extern UINT32 Gpio_read_buttons(void); extern void Gpio_set_backlight(UINT32 level); diff --git a/src/main.c b/src/main.c index 1d8525b..d56555b 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ #include #include #include "scode.h" +#include "config.h" #include "gpio.h" #include "log.h" #include "fbinit.h" @@ -29,17 +30,16 @@ int main(int argc, char *argv[]) int running = 1; MSG msg; char *tmp; - + Time_init(); + if (FAILED(Config_setup())) + return EXIT_FAILURE; if (FAILED(Fb_setup())) return EXIT_FAILURE; - atexit(Fb_cleanup); if (FAILED(Gpio_setup())) return EXIT_FAILURE; - atexit(Gpio_cleanup); if (FAILED(Sys_enable_input())) return EXIT_FAILURE; - atexit(Sys_disable_input); Log(LINFO, "Pausing at startup."); sleep(5); /* wait to show off splash screen */ diff --git a/src/msg_queue.c b/src/msg_queue.c index add55ae..fbe483e 100644 --- a/src/msg_queue.c +++ b/src/msg_queue.c @@ -56,7 +56,7 @@ void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *at if (nattrs > MSG_ATTRCOUNT) nattrs = MSG_ATTRCOUNT; if (nattrs > 0) - memcpy(&(tmpmsg.attrs), attrs, sizeof(uintptr_t) * nattrs); + memcpy(&(tmpmsg.attrs), attrs, sizeof(UINT_PTR) * nattrs); tmpmsg.timestamp = Time_since_start(); post_internal(queue, &tmpmsg); } diff --git a/src/sysinput.c b/src/sysinput.c index 59c503b..12aca3f 100644 --- a/src/sysinput.c +++ b/src/sysinput.c @@ -8,8 +8,6 @@ #include "gpio.h" #include "time_func.h" -#define DEBOUNCE_BUTTON_MSEC 100 - PMSG_QUEUE Sys_Queue = NULL; static pthread_t ithread; @@ -40,7 +38,7 @@ static void *input_thread(void *arg) continue; if (up & mask) { - button_event_ok[attr - 1] = now + DEBOUNCE_BUTTON_MSEC; + button_event_ok[attr - 1] = now + Gconfig.button_debounce; Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr); } else if (down & mask) @@ -54,12 +52,20 @@ static void *input_thread(void *arg) return NULL; } +static void do_disable_input(void) +{ + running = 0; + pthread_join(ithread, NULL); + Mq_destroy(Sys_Queue); + Sys_Queue = NULL; +} + HRESULT Sys_enable_input(void) { HRESULT rc = S_OK; int threadrc; - Sys_Queue = Mq_alloc(64); + Sys_Queue = Mq_alloc(Gconfig.sys_mq_length); if (!Sys_Queue) { Log(LFATAL, "Unable to allocate system message queue."); @@ -72,13 +78,11 @@ HRESULT Sys_enable_input(void) rc = SCODE_FROM_ERRNO(threadrc); Log(LFATAL, "Unable to start system input thread (%08X).", rc); } + if (SUCCEEDED(rc)) + { + rc = Config_exitfunc(do_disable_input); + if (FAILED(rc)) + do_disable_input(); + } return rc; } - -void Sys_disable_input(void) -{ - running = 0; - pthread_join(ithread, NULL); - Mq_destroy(Sys_Queue); - Sys_Queue = NULL; -} diff --git a/src/sysinput.h b/src/sysinput.h index 60b7833..8f316d0 100644 --- a/src/sysinput.h +++ b/src/sysinput.h @@ -7,6 +7,5 @@ extern PMSG_QUEUE Sys_Queue; extern HRESULT Sys_enable_input(void); -extern void Sys_disable_input(void); #endif /* __SYSINPUT_H_INCLUDED */