added global configuration data block and our own "atexit" type mechanism

that doesn't depend on enough free slots in the C library
This commit is contained in:
Amy G. Bowersox 2019-12-06 22:06:05 -07:00
parent 5e2269bf2b
commit e2946fc714
10 changed files with 155 additions and 55 deletions

70
src/config.c Normal file
View File

@ -0,0 +1,70 @@
#include <stdlib.h>
#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;
}

19
src/config.h Normal file
View File

@ -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 */

View File

@ -6,6 +6,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <linux/fb.h> #include <linux/fb.h>
#include "config.h"
#include "log.h" #include "log.h"
#include "fbinit.h" #include "fbinit.h"
#include "scode.h" #include "scode.h"
@ -27,13 +28,25 @@ inline static UINT16 makemask(unsigned offset, unsigned length)
return (UINT16)(((1 << length) - 1) << offset); 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 Fb_setup(void)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
struct fb_fix_screeninfo fixed; struct fb_fix_screeninfo fixed;
struct fb_var_screeninfo var; struct fb_var_screeninfo var;
fb_fd = open("/dev/fb1", O_RDWR); fb_fd = open(Gconfig.framebuffer_device, O_RDWR);
if (fb_fd == -1) if (fb_fd == -1)
{ {
hr = ERRNO_AS_SCODE; hr = ERRNO_AS_SCODE;
@ -89,21 +102,12 @@ HRESULT Fb_setup(void)
/* additional setup here */ /* additional setup here */
hr = Config_exitfunc(do_cleanup);
if (FAILED(hr))
do_cleanup();
return hr; 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) void Fb_clear(void)
{ {
memset(Fb_Ptr, 0, local_info.screenbytes); memset(Fb_Ptr, 0, local_info.screenbytes);

View File

@ -27,7 +27,6 @@ extern PCFBINFO Fb_Info;
extern UINT16 *Fb_Ptr; extern UINT16 *Fb_Ptr;
extern HRESULT Fb_setup(void); extern HRESULT Fb_setup(void);
extern void Fb_cleanup(void);
extern void Fb_clear(void); extern void Fb_clear(void);
#endif /* __FBINIT_H_INCLUDED */ #endif /* __FBINIT_H_INCLUDED */

View File

@ -1,5 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <bcm2835.h> #include <bcm2835.h>
#include "config.h"
#include "log.h" #include "log.h"
#include "scode.h" #include "scode.h"
#include "gpio.h" #include "gpio.h"
@ -12,8 +13,31 @@
#define PWM_BACKLIGHT 0 #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 Gpio_setup(void)
{ {
HRESULT hr;
if (!bcm2835_init()) if (!bcm2835_init())
{ {
Log(LFATAL, "Error initializing BCM2835 library"); 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_range(PWM_BACKLIGHT, GSB_BACKLIGHT_MAX + 1);
bcm2835_pwm_set_data(PWM_BACKLIGHT, GSB_BACKLIGHT_MAX); bcm2835_pwm_set_data(PWM_BACKLIGHT, GSB_BACKLIGHT_MAX);
return S_OK; hr = Config_exitfunc(do_cleanup);
} if (FAILED(hr))
do_cleanup();
void Gpio_cleanup(void) return hr;
{
/* 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");
} }
UINT32 Gpio_read_buttons(void) UINT32 Gpio_read_buttons(void)

View File

@ -13,7 +13,6 @@
#define GSB_BACKLIGHT_MAX 1023 #define GSB_BACKLIGHT_MAX 1023
extern HRESULT Gpio_setup(void); extern HRESULT Gpio_setup(void);
extern void Gpio_cleanup(void);
extern UINT32 Gpio_read_buttons(void); extern UINT32 Gpio_read_buttons(void);
extern void Gpio_set_backlight(UINT32 level); extern void Gpio_set_backlight(UINT32 level);

View File

@ -2,6 +2,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "scode.h" #include "scode.h"
#include "config.h"
#include "gpio.h" #include "gpio.h"
#include "log.h" #include "log.h"
#include "fbinit.h" #include "fbinit.h"
@ -29,17 +30,16 @@ int main(int argc, char *argv[])
int running = 1; int running = 1;
MSG msg; MSG msg;
char *tmp; char *tmp;
Time_init(); Time_init();
if (FAILED(Config_setup()))
return EXIT_FAILURE;
if (FAILED(Fb_setup())) if (FAILED(Fb_setup()))
return EXIT_FAILURE; return EXIT_FAILURE;
atexit(Fb_cleanup);
if (FAILED(Gpio_setup())) if (FAILED(Gpio_setup()))
return EXIT_FAILURE; return EXIT_FAILURE;
atexit(Gpio_cleanup);
if (FAILED(Sys_enable_input())) if (FAILED(Sys_enable_input()))
return EXIT_FAILURE; return EXIT_FAILURE;
atexit(Sys_disable_input);
Log(LINFO, "Pausing at startup."); Log(LINFO, "Pausing at startup.");
sleep(5); /* wait to show off splash screen */ sleep(5); /* wait to show off splash screen */

View File

@ -56,7 +56,7 @@ void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *at
if (nattrs > MSG_ATTRCOUNT) if (nattrs > MSG_ATTRCOUNT)
nattrs = MSG_ATTRCOUNT; nattrs = MSG_ATTRCOUNT;
if (nattrs > 0) if (nattrs > 0)
memcpy(&(tmpmsg.attrs), attrs, sizeof(uintptr_t) * nattrs); memcpy(&(tmpmsg.attrs), attrs, sizeof(UINT_PTR) * nattrs);
tmpmsg.timestamp = Time_since_start(); tmpmsg.timestamp = Time_since_start();
post_internal(queue, &tmpmsg); post_internal(queue, &tmpmsg);
} }

View File

@ -8,8 +8,6 @@
#include "gpio.h" #include "gpio.h"
#include "time_func.h" #include "time_func.h"
#define DEBOUNCE_BUTTON_MSEC 100
PMSG_QUEUE Sys_Queue = NULL; PMSG_QUEUE Sys_Queue = NULL;
static pthread_t ithread; static pthread_t ithread;
@ -40,7 +38,7 @@ static void *input_thread(void *arg)
continue; continue;
if (up & mask) 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); Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
} }
else if (down & mask) else if (down & mask)
@ -54,12 +52,20 @@ static void *input_thread(void *arg)
return NULL; 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 Sys_enable_input(void)
{ {
HRESULT rc = S_OK; HRESULT rc = S_OK;
int threadrc; int threadrc;
Sys_Queue = Mq_alloc(64); Sys_Queue = Mq_alloc(Gconfig.sys_mq_length);
if (!Sys_Queue) if (!Sys_Queue)
{ {
Log(LFATAL, "Unable to allocate system message queue."); Log(LFATAL, "Unable to allocate system message queue.");
@ -72,13 +78,11 @@ HRESULT Sys_enable_input(void)
rc = SCODE_FROM_ERRNO(threadrc); rc = SCODE_FROM_ERRNO(threadrc);
Log(LFATAL, "Unable to start system input thread (%08X).", rc); 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; return rc;
} }
void Sys_disable_input(void)
{
running = 0;
pthread_join(ithread, NULL);
Mq_destroy(Sys_Queue);
Sys_Queue = NULL;
}

View File

@ -7,6 +7,5 @@
extern PMSG_QUEUE Sys_Queue; extern PMSG_QUEUE Sys_Queue;
extern HRESULT Sys_enable_input(void); extern HRESULT Sys_enable_input(void);
extern void Sys_disable_input(void);
#endif /* __SYSINPUT_H_INCLUDED */ #endif /* __SYSINPUT_H_INCLUDED */