added more documentation
This commit is contained in:
parent
fc0c0f05fc
commit
7e098aa63a
27
src/config.c
27
src/config.c
|
@ -7,6 +7,7 @@
|
|||
#include "scode.h"
|
||||
#include "log.h"
|
||||
|
||||
/* command line options for UPIWIN */
|
||||
static const struct option long_options[] = {
|
||||
{"framebuffer", required_argument, 0, 'F'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
|
@ -16,6 +17,7 @@ static const struct option long_options[] = {
|
|||
|
||||
static const char *short_options = "F:hT:";
|
||||
|
||||
/* printed to stdout when upiwin is executed with -h/--help option */
|
||||
static const char *helptext =
|
||||
"UPIWIN - Micro Pi Windows server program\n\n"
|
||||
"Usage: upiwin [options] scriptname [scriptargs]\n\n"
|
||||
|
@ -25,19 +27,20 @@ static const char *helptext =
|
|||
" -T,--touchscreen - Specifies the touchscreen device name\n"
|
||||
"";
|
||||
|
||||
#define EXITFUNCBLOCK_FUNCCOUNT 64
|
||||
#define EXITFUNCBLOCK_FUNCCOUNT 64 /* number of exit functions per function block */
|
||||
|
||||
/* exit functions are stored in these data blocks */
|
||||
typedef struct tagEXITFUNCBLOCK
|
||||
{
|
||||
struct tagEXITFUNCBLOCK *next;
|
||||
int num_funcs;
|
||||
PEXITFUNC funcs[EXITFUNCBLOCK_FUNCCOUNT];
|
||||
struct tagEXITFUNCBLOCK *next; /* chained in single linked list */
|
||||
int num_funcs; /* number of functions this block contains */
|
||||
PEXITFUNC funcs[EXITFUNCBLOCK_FUNCCOUNT]; /* pointers to functions */
|
||||
} EXITFUNCBLOCK, *PEXITFUNCBLOCK;
|
||||
|
||||
/* The global configuration data */
|
||||
GLOBAL_CONFIG Gconfig;
|
||||
|
||||
static PEXITFUNCBLOCK exitfuncs = NULL;
|
||||
static PEXITFUNCBLOCK exitfuncs = NULL; /* pointer to head of exit function chain */
|
||||
|
||||
static void run_exit_funcs(void)
|
||||
{
|
||||
|
@ -50,6 +53,7 @@ static void run_exit_funcs(void)
|
|||
exitfuncs = p->next;
|
||||
for (i = p->num_funcs - 1; i >= 0; i--)
|
||||
{
|
||||
/* execute functions in LIFO order */
|
||||
ASSERT(p->funcs[i]);
|
||||
(*(p->funcs[i]))();
|
||||
}
|
||||
|
@ -59,6 +63,7 @@ static void run_exit_funcs(void)
|
|||
|
||||
static void init_defaults(void)
|
||||
{
|
||||
memset(&Gconfig, 0, sizeof(GLOBAL_CONFIG));
|
||||
Gconfig.framebuffer_device = "/dev/fb1";
|
||||
Gconfig.touchscreen_device = "/dev/input/touchscreen";
|
||||
Gconfig.button_debounce = 100;
|
||||
|
@ -79,7 +84,7 @@ static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed)
|
|||
break;
|
||||
switch (c)
|
||||
{
|
||||
case 'F':
|
||||
case 'F': /* frame buffer device name */
|
||||
pstr = strdup(optarg);
|
||||
if (!pstr)
|
||||
{
|
||||
|
@ -91,11 +96,11 @@ static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed)
|
|||
parsed->framebuffer_device = pstr;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case 'h': /* show help */
|
||||
help = TRUE;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
case 'T': /* touchscreen device name */
|
||||
pstr = strdup(optarg);
|
||||
if (!pstr)
|
||||
{
|
||||
|
@ -138,10 +143,16 @@ HRESULT Config_setup(int argc, char *argv[])
|
|||
Log(LFATAL, "Unable to set up exit function mechanism");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
/* set defaults */
|
||||
init_defaults();
|
||||
|
||||
/* evaluate command line */
|
||||
hr = parse_cmdline(argc, argv, &from_commandline);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
|
||||
/* command line overrides everything */
|
||||
overlay_config(&from_commandline);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
11
src/config.h
11
src/config.h
|
@ -5,14 +5,15 @@
|
|||
|
||||
typedef void (*PEXITFUNC)(void);
|
||||
|
||||
/* global configuration data for UPIWIN */
|
||||
typedef struct tagGLOBAL_CONFIG {
|
||||
PCSTR framebuffer_device;
|
||||
PCSTR touchscreen_device;
|
||||
UINT32 button_debounce;
|
||||
UINT32 sys_mq_length;
|
||||
PCSTR framebuffer_device; /* name of frame buffer device */
|
||||
PCSTR touchscreen_device; /* name of touchscreen device */
|
||||
UINT32 button_debounce; /* minimum time between button up and next button down (ms) */
|
||||
UINT32 sys_mq_length; /* length of system message queue */
|
||||
} GLOBAL_CONFIG;
|
||||
|
||||
extern GLOBAL_CONFIG Gconfig;
|
||||
extern GLOBAL_CONFIG Gconfig; /* one global configuration to rule them all */
|
||||
|
||||
extern HRESULT Config_setup(int argc, char *argv[]);
|
||||
extern HRESULT Config_exitfunc(PEXITFUNC pfn);
|
||||
|
|
18
src/fbinit.c
18
src/fbinit.c
|
@ -16,12 +16,13 @@ extern uint8_t _binary_splash_bin_start[];
|
|||
extern uint8_t _binary_splash_bin_end;
|
||||
extern uint8_t _binary_splash_bin_size;
|
||||
|
||||
static int fb_fd = -1;
|
||||
static int fb_fd = -1; /* framebuffer file descriptor */
|
||||
|
||||
/* frame buffer information */
|
||||
static FBINFO local_info;
|
||||
PCFBINFO Fb_Info = &local_info;
|
||||
|
||||
UINT16 *Fb_Ptr = NULL;
|
||||
UINT16 *Fb_Ptr = NULL; /* pointer to memory-mapped frame buffer */
|
||||
|
||||
inline static UINT16 makemask(unsigned offset, unsigned length)
|
||||
{
|
||||
|
@ -30,12 +31,11 @@ inline static UINT16 makemask(unsigned offset, unsigned length)
|
|||
|
||||
static void do_cleanup(void)
|
||||
{
|
||||
/* additional cleanup here */
|
||||
|
||||
/* black out the display */
|
||||
memset(Fb_Ptr, 0, local_info.screenbytes);
|
||||
munmap((void *)Fb_Ptr, local_info.screenbytes);
|
||||
Fb_Ptr = NULL;
|
||||
|
||||
munmap((void *)Fb_Ptr, local_info.screenbytes);
|
||||
Fb_Ptr = NULL;
|
||||
close(fb_fd);
|
||||
fb_fd = -1;
|
||||
}
|
||||
|
@ -50,10 +50,11 @@ HRESULT Fb_setup(void)
|
|||
if (fb_fd == -1)
|
||||
{
|
||||
hr = ERRNO_AS_SCODE;
|
||||
Log(LFATAL, "Unable to open framebuffer (%08X)", hr);
|
||||
Log(LFATAL, "Unable to open framebuffer device %s (%08X)", Gconfig.framebuffer_device, hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* fixed info is needed to get the memory parameters for the display */
|
||||
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixed))
|
||||
{
|
||||
hr = ERRNO_AS_SCODE;
|
||||
|
@ -64,6 +65,7 @@ HRESULT Fb_setup(void)
|
|||
local_info.linebytes = fixed.line_length;
|
||||
local_info.screenbytes = fixed.smem_len;
|
||||
|
||||
/* variable info is used to get scren geometry and color info */
|
||||
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
|
||||
{
|
||||
hr = ERRNO_AS_SCODE;
|
||||
|
@ -100,8 +102,6 @@ HRESULT Fb_setup(void)
|
|||
/* display the splash screen */
|
||||
memcpy(Fb_Ptr, _binary_splash_bin_start, (size_t)(&_binary_splash_bin_size));
|
||||
|
||||
/* additional setup here */
|
||||
|
||||
hr = Config_exitfunc(do_cleanup);
|
||||
if (FAILED(hr))
|
||||
do_cleanup();
|
||||
|
|
37
src/fbinit.h
37
src/fbinit.h
|
@ -3,28 +3,29 @@
|
|||
|
||||
#include "wintype.h"
|
||||
|
||||
/* info about the frame buffer */
|
||||
typedef struct tagFBINFO {
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
UINT32 virtual_width;
|
||||
UINT32 virtual_height;
|
||||
UINT32 bpp;
|
||||
UINT32 linebytes;
|
||||
UINT32 screenbytes;
|
||||
UINT16 red_offset;
|
||||
UINT16 red_length;
|
||||
UINT16 red_mask;
|
||||
UINT16 green_offset;
|
||||
UINT16 green_length;
|
||||
UINT16 green_mask;
|
||||
UINT16 blue_offset;
|
||||
UINT16 blue_length;
|
||||
UINT16 blue_mask;
|
||||
UINT32 width; /* screen width */
|
||||
UINT32 height; /* screen height */
|
||||
UINT32 virtual_width; /* virtual screen width */
|
||||
UINT32 virtual_height; /* virtual screen height */
|
||||
UINT32 bpp; /* bits per pixel (16) */
|
||||
UINT32 linebytes; /* number of bytes per line */
|
||||
UINT32 screenbytes; /* number of bytes for the entire screen */
|
||||
UINT16 red_offset; /* offset of "red" bits within pixel word (11) */
|
||||
UINT16 red_length; /* number of "red" bits within pixel word (5) */
|
||||
UINT16 red_mask; /* mask for the "red" bits in a pixel word */
|
||||
UINT16 green_offset; /* offset of "green" bits within pixel word (5) */
|
||||
UINT16 green_length; /* number of "green" bits within pixel word (6) */
|
||||
UINT16 green_mask; /* mask for the "green" bits in a pixel word */
|
||||
UINT16 blue_offset; /* offset of "blue" bits within pixel word (0) */
|
||||
UINT16 blue_length; /* number of "blue" bits within pixel word (5) */
|
||||
UINT16 blue_mask; /* mask for the "blue" bits in a pixel word */
|
||||
} FBINFO;
|
||||
typedef const FBINFO * const PCFBINFO;
|
||||
|
||||
extern PCFBINFO Fb_Info;
|
||||
extern UINT16 *Fb_Ptr;
|
||||
extern PCFBINFO Fb_Info; /* pointer to screen information */
|
||||
extern UINT16 *Fb_Ptr; /* pointer to memory-mapped screen buffer */
|
||||
|
||||
extern HRESULT Fb_setup(void);
|
||||
extern void Fb_clear(void);
|
||||
|
|
|
@ -25,6 +25,7 @@ void Fb_line(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor)
|
|||
INT32 dx = x2 - x1;
|
||||
INT32 dy = y2 - y1;
|
||||
|
||||
/* uses Bresenham's line algorithm with fixed-point arithmetic */
|
||||
if (ABS(dx) < ABS(dy))
|
||||
{
|
||||
if (y1 > y2)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "wintype.h"
|
||||
|
||||
/* Some predefined "primitive" color values */
|
||||
#define FBPRIMCLR_BLACK 0x0000
|
||||
#define FBPRIMCLR_RED 0xF800
|
||||
#define FBPRIMCLR_GREEN 0x07E0
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
#include "scode.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/* GPIO lines used by various peripheral devices */
|
||||
#define GLINE_BUTTON1 17
|
||||
#define GLINE_BUTTON2 22
|
||||
#define GLINE_BUTTON3 23
|
||||
#define GLINE_BUTTON4 27
|
||||
#define GLINE_BACKLIGHT 18
|
||||
|
||||
#define PWM_BACKLIGHT 0
|
||||
#define PWM_BACKLIGHT 0 /* PWM channel used for backlight */
|
||||
|
||||
static void do_cleanup(void)
|
||||
{
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
|
||||
#include "wintype.h"
|
||||
|
||||
#define GPIO_BUTTON_COUNT 4
|
||||
#define GPIO_BUTTON_COUNT 4 /* number of GPIO buttons we have */
|
||||
|
||||
/* state flags for the GPIO buttons */
|
||||
#define GRB_STATE_BUTTON1 (1 << 0)
|
||||
#define GRB_STATE_BUTTON2 (1 << 1)
|
||||
#define GRB_STATE_BUTTON3 (1 << 2)
|
||||
#define GRB_STATE_BUTTON4 (1 << 3)
|
||||
|
||||
#define GSB_BACKLIGHT_MAX 1023
|
||||
#define GSB_BACKLIGHT_MAX 1023 /* maximum level for backlight */
|
||||
|
||||
extern HRESULT Gpio_setup(void);
|
||||
extern UINT32 Gpio_read_buttons(void);
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
#include <sys/time.h>
|
||||
#include "log.h"
|
||||
|
||||
/* string equivalents to the severity values */
|
||||
static const char *severities[] = { "FATAL", "ERROR", "WARN ", "INFO ", "DEBUG" };
|
||||
|
||||
static FILE *logfile = stdout; /* log file pointer */
|
||||
|
||||
void Log(int level, const char *format, ...)
|
||||
{
|
||||
va_list argp;
|
||||
|
@ -21,7 +24,7 @@ void Log(int level, const char *format, ...)
|
|||
gettimeofday(&tv, NULL);
|
||||
localtime_r(&(tv.tv_sec), &tm);
|
||||
strftime(timestamp, 32, "%F %T", &tm);
|
||||
printf("%s.%06u %s %s\n", timestamp, tv.tv_usec, severities[level], buf);
|
||||
fprintf(logfile, "%s.%06u %s %s\n", timestamp, tv.tv_usec, severities[level], buf);
|
||||
}
|
||||
|
||||
void Log_assert_failed(const char *test, const char *file, int line)
|
||||
|
|
13
src/log.h
13
src/log.h
|
@ -1,18 +1,21 @@
|
|||
#ifndef __LOG_H_INCLUDED
|
||||
#define __LOG_H_INCLUDED
|
||||
|
||||
#define LFATAL 0
|
||||
#define LERROR 1
|
||||
#define LWARN 2
|
||||
#define LINFO 3
|
||||
#define LDEBUG 4
|
||||
/* Logging level severities */
|
||||
#define LFATAL 0 /* fatal error */
|
||||
#define LERROR 1 /* error */
|
||||
#define LWARN 2 /* warning */
|
||||
#define LINFO 3 /* information */
|
||||
#define LDEBUG 4 /* debugging */
|
||||
|
||||
extern void Log(int level, const char *format, ...);
|
||||
extern void Log_assert_failed(const char *test, const char *file, int line);
|
||||
|
||||
/* Current file name definitions for assert macros */
|
||||
#define THIS_FILE __FILE__
|
||||
#define DECLARE_THIS_FILE() static const char THIS_FILE[] = __FILE__
|
||||
|
||||
/* Assert macros */
|
||||
#ifdef DEBUG_ASSERT
|
||||
#define ASSERT(x) ((x) ? (void)0 : Log_assert_failed(#x, THIS_FILE, __LINE__))
|
||||
#define VERIFY(x) ASSERT(x)
|
||||
|
|
|
@ -35,6 +35,7 @@ int main(int argc, char *argv[])
|
|||
MSG msg;
|
||||
char *tmp;
|
||||
|
||||
/* initialization sequence */
|
||||
Time_init();
|
||||
hr = Config_setup(argc, argv);
|
||||
if (FAILED(hr))
|
||||
|
@ -48,7 +49,7 @@ int main(int argc, char *argv[])
|
|||
if (FAILED(Sys_enable_input()))
|
||||
return EXIT_FAILURE;
|
||||
Log(LINFO, "Pausing at startup.");
|
||||
sleep(5); /* wait to show off splash screen */
|
||||
sleep(3); /* wait to show off splash screen */
|
||||
|
||||
Fb_clear();
|
||||
/* temporary drawing here */
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
#ifndef __MSG_QUEUE_H_INCLUDED
|
||||
#define __MSG_QUEUE_H_INCLUDED
|
||||
|
||||
#include <pthread.h>
|
||||
#include "wintype.h"
|
||||
#include "msg.h"
|
||||
|
||||
/* internal structure of a message queue */
|
||||
typedef struct tagMSG_QUEUE {
|
||||
struct tagMSG_QUEUE *next;
|
||||
PMSG startbound;
|
||||
PMSG endbound;
|
||||
PMSG head;
|
||||
PMSG tail;
|
||||
UINT32 nentries;
|
||||
pthread_mutex_t mutex;
|
||||
MSG messagestore[0];
|
||||
struct tagMSG_QUEUE *next; /* allow us to be in a singly-linked list */
|
||||
PMSG startbound; /* start boundary for message buffer */
|
||||
PMSG endbound; /* end boundary for message buffer */
|
||||
PMSG head; /* head pointer of message queue */
|
||||
PMSG tail; /* tail pointer of message queue */
|
||||
UINT32 nentries; /* number of entries possible in message buffer */
|
||||
pthread_mutex_t mutex; /* controls access to queue from multiple threads */
|
||||
MSG messagestore[0]; /* message buffer */
|
||||
} MSG_QUEUE, *PMSG_QUEUE;
|
||||
|
||||
#define PEEK_REMOVE 0x0001
|
||||
#define PEEK_NOREMOVE 0x0000
|
||||
/* flags to Mq_peek */
|
||||
#define PEEK_REMOVE 0x0001 /* remove message if found */
|
||||
#define PEEK_NOREMOVE 0x0000 /* do not remove message if found */
|
||||
|
||||
extern PMSG_QUEUE Mq_alloc(UINT32 nentries);
|
||||
extern void Mq_destroy(PMSG_QUEUE queue);
|
||||
|
|
|
@ -13,20 +13,22 @@
|
|||
#include "gpio.h"
|
||||
#include "time_func.h"
|
||||
|
||||
#define INPUT_EVENT_BATCH 16
|
||||
#define INPUT_EVENT_BATCH 16 /* number of events to retrieve from touchscreen at once */
|
||||
|
||||
PMSG_QUEUE Sys_Queue = NULL;
|
||||
PMSG_QUEUE Sys_Queue = NULL; /* system message queue */
|
||||
static int ts_fd = 0; /* file descriptor for touchscreen */
|
||||
|
||||
static pthread_t ithread;
|
||||
static volatile sig_atomic_t running = 1;
|
||||
static int ts_fd = 0;
|
||||
static pthread_t ithread; /* input thread handle */
|
||||
static volatile sig_atomic_t running = 1; /* "running" flag for input thread */
|
||||
|
||||
static UINT32 last_bstate = 0;
|
||||
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT];
|
||||
/* Local data for poll_buttons() */
|
||||
static UINT32 last_bstate = 0; /* previous button state */
|
||||
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT]; /* timestamps to debounce events */
|
||||
|
||||
static UINT_PTR touch_x = 0;
|
||||
static UINT_PTR touch_y = 0;
|
||||
static UINT32 touch_nextmsg = WM_TOUCHMOVE;
|
||||
/* Local data for poll_touchscreen() */
|
||||
static UINT_PTR touch_x = 0; /* X coordinate to send with next message */
|
||||
static UINT_PTR touch_y = 0; /* Y coordinate to send with next message */
|
||||
static UINT32 touch_nextmsg = WM_TOUCHMOVE; /* identifier of next message to send */
|
||||
|
||||
static void poll_buttons(void)
|
||||
{
|
||||
|
@ -44,9 +46,10 @@ static void poll_buttons(void)
|
|||
for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1)
|
||||
{
|
||||
if (now < button_event_ok[attr - 1])
|
||||
continue;
|
||||
continue; /* this is a "contact bounce" event, don't bother */
|
||||
if (up & mask)
|
||||
{
|
||||
/* reset contact bounce timer - only seems to happen after button releases */
|
||||
button_event_ok[attr - 1] = now + Gconfig.button_debounce;
|
||||
Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
|
||||
}
|
||||
|
@ -75,10 +78,12 @@ static void poll_touchscreen(void)
|
|||
Log(LERROR, "Unexpected end of file reading from touchscreen device");
|
||||
return;
|
||||
}
|
||||
|
||||
nev = nb / sizeof(struct input_event);
|
||||
xerrno = nev * sizeof(struct input_event);
|
||||
if (nb > xerrno)
|
||||
Log(LERROR, "read %d bytes from touchscreen but we can only use %d", nb, xerrno);
|
||||
|
||||
for (i=0; i<nev; i++)
|
||||
{
|
||||
switch (buffer[i].type)
|
||||
|
@ -111,6 +116,7 @@ static void poll_touchscreen(void)
|
|||
|
||||
static void *input_thread(void *arg)
|
||||
{
|
||||
/* clear all state at startup */
|
||||
last_bstate = 0;
|
||||
memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP));
|
||||
touch_x = touch_y = 0;
|
||||
|
@ -151,7 +157,7 @@ HRESULT Sys_enable_input(void)
|
|||
{
|
||||
rc = ERRNO_AS_SCODE;
|
||||
Mq_destroy(Sys_Queue);
|
||||
Log(LFATAL, "Unable to open touchscreen device (%08X).", rc);
|
||||
Log(LFATAL, "Unable to open touchscreen device %s (%08X).", Gconfig.touchscreen_device, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <sys/time.h>
|
||||
#include "time_func.h"
|
||||
|
||||
static TIMESTAMP start_timestamp = 0;
|
||||
static TIMESTAMP start_timestamp = 0; /* time since epoch at start of run */
|
||||
|
||||
TIMESTAMP Time_since_epoch(void)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define INT64_BITS 64
|
||||
#define UINT64_BITS 64
|
||||
|
||||
#define LOG_PTRSIZE 2 /* log2(sizeof(void *)) */
|
||||
#define LOG_PTRSIZE 2 /* log2(sizeof(void *)) */
|
||||
|
||||
#define LOG_INTSIZE 2 /* log2(sizeof(int)) */
|
||||
#define LOG_UINTSIZE 2 /* log2(sizeof(UINT32)) */
|
||||
|
|
Loading…
Reference in New Issue
Block a user