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"
 | 
			
		||||
@ -31,15 +32,14 @@ int main(int argc, char *argv[])
 | 
			
		||||
  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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user