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:
parent
5e2269bf2b
commit
e2946fc714
70
src/config.c
Normal file
70
src/config.c
Normal 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
19
src/config.h
Normal 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 */
|
30
src/fbinit.c
30
src/fbinit.c
|
@ -6,6 +6,7 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/fb.h>
|
||||
#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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
50
src/gpio.c
50
src/gpio.c
|
@ -1,5 +1,6 @@
|
|||
#include <stdint.h>
|
||||
#include <bcm2835.h>
|
||||
#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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue
Block a user