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/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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
50
src/gpio.c
50
src/gpio.c
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user