implemented the system input queue and system input thread
This commit is contained in:
parent
59e8fa59d5
commit
87db1f4d02
|
@ -1,4 +1,4 @@
|
||||||
OBJS=main.o log.o gpio.o
|
OBJS=main.o sysinput.o log.o gpio.o msg_queue.o time_func.o
|
||||||
LIBS=
|
LIBS=
|
||||||
|
|
||||||
upiwin: $(OBJS)
|
upiwin: $(OBJS)
|
||||||
|
|
16
src/gpio.c
16
src/gpio.c
|
@ -182,9 +182,23 @@ void Gpio_cleanup(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Gpio_read_buttons(void)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (gpio_input(GLINE_BUTTON1) == 0)
|
||||||
|
rc |= STATE_BUTTON1;
|
||||||
|
if (gpio_input(GLINE_BUTTON2) == 0)
|
||||||
|
rc |= STATE_BUTTON2;
|
||||||
|
if (gpio_input(GLINE_BUTTON3) == 0)
|
||||||
|
rc |= STATE_BUTTON3;
|
||||||
|
if (gpio_input(GLINE_BUTTON4) == 0)
|
||||||
|
rc |= STATE_BUTTON4;
|
||||||
|
}
|
||||||
|
|
||||||
int Gpio_poll_buttons(void)
|
int Gpio_poll_buttons(void)
|
||||||
{
|
{
|
||||||
int new_state = 0;
|
int new_state = Gpio_read_buttons();
|
||||||
int tmp, ndx, mask;
|
int tmp, ndx, mask;
|
||||||
|
|
||||||
if (gpio_input(GLINE_BUTTON1) == 0)
|
if (gpio_input(GLINE_BUTTON1) == 0)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
extern int Gpio_setup(void);
|
extern int Gpio_setup(void);
|
||||||
extern void Gpio_cleanup(void);
|
extern void Gpio_cleanup(void);
|
||||||
|
extern int Gpio_read_buttons(void);
|
||||||
extern int Gpio_poll_buttons(void);
|
extern int Gpio_poll_buttons(void);
|
||||||
|
|
||||||
#endif /* __GPIO_H_INCLUDED */
|
#endif /* __GPIO_H_INCLUDED */
|
||||||
|
|
30
src/main.c
30
src/main.c
|
@ -1,16 +1,42 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "time_func.h"
|
||||||
|
#include "sysinput.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
TimeInit();
|
||||||
if (Gpio_setup() != 0)
|
if (Gpio_setup() != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
atexit(Gpio_cleanup);
|
atexit(Gpio_cleanup);
|
||||||
|
if (SysEnableInput() != 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
atexit(SysDisableInput);
|
||||||
|
|
||||||
Log(LINFO, "System ready.");
|
Log(LINFO, "System ready.");
|
||||||
|
|
||||||
for (;;) {
|
for (;;)
|
||||||
Gpio_poll_buttons();
|
{
|
||||||
|
if (MqPeek(Sys_Queue, &msg, PEEK_REMOVE))
|
||||||
|
{
|
||||||
|
switch (msg.message)
|
||||||
|
{
|
||||||
|
case WM_HWBUTTONDOWN:
|
||||||
|
Log(LINFO, "Button %d was pressed.", (int)(msg.attrs[0]));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_HWBUTTONUP:
|
||||||
|
Log(LINFO, "Button %d was released.", (int)(msg.attrs[0]));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
20
src/msg.h
Normal file
20
src/msg.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef __MSG_H_INCLUDED
|
||||||
|
#define __MSG_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wintype.h"
|
||||||
|
|
||||||
|
#define MSG_ATTRCOUNT 2
|
||||||
|
|
||||||
|
typedef tagMSG {
|
||||||
|
uintptr_t target;
|
||||||
|
unsigned message;
|
||||||
|
uintptr_t attrs[MSG_ATTRCOUNT];
|
||||||
|
TIMESTAMP timestamp;
|
||||||
|
} MSG, *PMSG;
|
||||||
|
|
||||||
|
#define WM_NULL 0x0000
|
||||||
|
|
||||||
|
#define WM_HWBUTTONDOWN 0x0020
|
||||||
|
#define WM_HWBUTTONUP 0x0021
|
||||||
|
|
||||||
|
#endif /* __MSG_H_INCLUDED */
|
92
src/msg_queue.c
Normal file
92
src/msg_queue.c
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "wintype.h"
|
||||||
|
#include "time_func.h"
|
||||||
|
#include "msg_queue.h"
|
||||||
|
|
||||||
|
PMSG_QUEUE MqAlloc(int nentries)
|
||||||
|
{
|
||||||
|
int sz = sizeof(MSG_QUEUE) + (nentries * sizeof(MSG));
|
||||||
|
PMSG_QUEUE rc;
|
||||||
|
|
||||||
|
rc = (PMSG_QUEUE)malloc(sz);
|
||||||
|
if (!rc)
|
||||||
|
return NULL;
|
||||||
|
memset(rc, 0 sz);
|
||||||
|
rc->startbound = &(rc->messagestore);
|
||||||
|
rc->endbound = rc->startbound + nentries;
|
||||||
|
rc->head = rc->tail = rc->startbound;
|
||||||
|
rc->nentries = nentries;
|
||||||
|
pthread_mutex_init(&(rc->mutex), NULL);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MqDestroy(PMSG_QUEUE queue)
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy(&(queue->mutex));
|
||||||
|
free(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void post_internal(PMSG_QUEUE queue, PMSG msg)
|
||||||
|
{
|
||||||
|
PMSG nexttail;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(queue->mutex));
|
||||||
|
nexttail = queue->tail + 1;
|
||||||
|
if (nexttail == queue->endbound)
|
||||||
|
nexttail = queue->startbound;
|
||||||
|
if (nexttail != queue->head)
|
||||||
|
{
|
||||||
|
memcpy(queue->tail, msg, sizeof(MSG));
|
||||||
|
queue->tail = nexttail;
|
||||||
|
}
|
||||||
|
/* else drop the message silently */
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(queue->mutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MqPost(PMSG_QUEUE queue, uintptr_t target, unsigned message, const uintptr_t *attrs, int nattrs)
|
||||||
|
{
|
||||||
|
MSG tmpmsg;
|
||||||
|
|
||||||
|
memset(&tmpmsg, 0, sizeof(MSG));
|
||||||
|
tmpmsg.target = target;
|
||||||
|
tmpmsg.message = message;
|
||||||
|
if (nattrs > MSG_ATTRCOUNT)
|
||||||
|
nattrs = MSG_ATTRCOUNT;
|
||||||
|
if (nattrs > 0)
|
||||||
|
memcpy(&(tmpmsg.attrs), attrs, sizeof(uintptr_t) * nattrs);
|
||||||
|
tmpmsg.timestamp = TimeSinceStart();
|
||||||
|
post_internal(queue, &tmpmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MqPost1(PMSG_QUEUE queue, uintptr_t target, unsigned message, uintptr_t attr1)
|
||||||
|
{
|
||||||
|
MSG tmpmsg;
|
||||||
|
|
||||||
|
memset(&tmpmsg, 0, sizeof(MSG));
|
||||||
|
tmpmsg.target = target;
|
||||||
|
tmpmsg.message = message;
|
||||||
|
tmpmsg.attrs[0] = attr1;
|
||||||
|
tmpmsg.timestamp = TimeSinceStart();
|
||||||
|
post_internal(queue, &tmpmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MqPeek(PMSG_QUEUE queue, PMSG msg, unsigned flags)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
PMSG nexthead;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(queue->mutex));
|
||||||
|
if (queue->head != queue->tail)
|
||||||
|
{
|
||||||
|
nexthead = queue->head + 1;
|
||||||
|
if (nexthead == queue->endbound)
|
||||||
|
nexthead = queue->startbound;
|
||||||
|
memcpy(msg, queue->head, sizeof(MSG));
|
||||||
|
if (flags & PEEK_REMOVE)
|
||||||
|
queue->head = nexthead;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&(queue->mutex));
|
||||||
|
return rc;
|
||||||
|
}
|
27
src/msg_queue.h
Normal file
27
src/msg_queue.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __MSG_QUEUE_H_INCLUDED
|
||||||
|
#define __MSG_QUEUE_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wintype.h"
|
||||||
|
#include "msg.h"
|
||||||
|
|
||||||
|
typedef struct tagMSG_QUEUE {
|
||||||
|
struct tagMSG_QUEUE *next;
|
||||||
|
PMSG startbound;
|
||||||
|
PMSG endbound;
|
||||||
|
PMSG head;
|
||||||
|
PMSG tail;
|
||||||
|
int nentries;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
MSG messagestore[0];
|
||||||
|
} MSG_QUEUE, *PMSG_QUEUE;
|
||||||
|
|
||||||
|
#define PEEK_REMOVE 0x0001
|
||||||
|
#define PEEK_NOREMOVE 0x0000
|
||||||
|
|
||||||
|
extern PMSG_QUEUE MqAlloc(int nentries);
|
||||||
|
extern void MqDestroy(PMSG_QUEUE queue);
|
||||||
|
extern void MqPost(PMSG_QUEUE queue, uintptr_t target, unsigned message, const uintptr_t *attrs, int nattrs);
|
||||||
|
extern void MqPost1(PMSG_QUEUE queue, uintptr_t target, unsigned message, uintptr_t attr1);
|
||||||
|
extern int MqPeek(PMSG_QUEUE queue, PMSG msg, unsigned flags);
|
||||||
|
|
||||||
|
#endif /* __MSG_QUEUE_H_INCLUDED */
|
68
src/sysinput.c
Normal file
68
src/sysinput.c
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "msg_queue.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
PMSG_QUEUE Sys_Queue = NULL;
|
||||||
|
|
||||||
|
static pthread_t ithread;
|
||||||
|
static volatile sig_atomic_t running = 1;
|
||||||
|
static int last_bstate = 0;
|
||||||
|
|
||||||
|
static void *input_thread(void *arg)
|
||||||
|
{
|
||||||
|
int st, tmp, mask;
|
||||||
|
uintptr_t attr;
|
||||||
|
|
||||||
|
while (running)
|
||||||
|
{
|
||||||
|
/* poll hardware buttons */
|
||||||
|
st = Gpio_read_buttons();
|
||||||
|
if (st != last_bstate)
|
||||||
|
{
|
||||||
|
tmp = last_state & ~st;
|
||||||
|
for (attr = 1, mask = 1; attr <= 4; attr++, mask <<= 1)
|
||||||
|
{
|
||||||
|
if (tmp & mask)
|
||||||
|
MqPost1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
|
||||||
|
}
|
||||||
|
tmp = st & ~last_state;
|
||||||
|
for (attr = 1, mask = 1; attr <= 4; attr++, mask <<= 1)
|
||||||
|
{
|
||||||
|
if (tmp & mask)
|
||||||
|
MqPost1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr);
|
||||||
|
}
|
||||||
|
last_bstate = st;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* additional poll activity here */
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SysEnableInput(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
Sys_Queue = MqAlloc(64);
|
||||||
|
if (!Sys_Queue)
|
||||||
|
{
|
||||||
|
Log(LFATAL, "Unable to allocate system message queue.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
running = 1;
|
||||||
|
rc = pthread_create(&ithread, NULL, input_thread, NULL);
|
||||||
|
if (rc != 0)
|
||||||
|
Log(LFATAL, "Unable to start system input thread (%d).", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysDisableInput(void)
|
||||||
|
{
|
||||||
|
running = 0;
|
||||||
|
pthread_join(ithread, NULL);
|
||||||
|
MqDestroy(Sys_Queue);
|
||||||
|
Sys_Queue = NULL;
|
||||||
|
}
|
11
src/sysinput.h
Normal file
11
src/sysinput.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef __SYSINPUT_H_INCLUDED
|
||||||
|
#define __SYSINPUT_H_INCLUDED
|
||||||
|
|
||||||
|
#include "msg_queue.h"
|
||||||
|
|
||||||
|
extern PMSG_QUEUE Sys_Queue;
|
||||||
|
|
||||||
|
extern int SysEnableInput(void);
|
||||||
|
extern void SysDisableInput(void);
|
||||||
|
|
||||||
|
#endif /* __SYSINPUT_H_INCLUDED */
|
25
src/time_func.c
Normal file
25
src/time_func.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include "time_func.h"
|
||||||
|
|
||||||
|
static TIMESTAMP start_timestamp = 0;
|
||||||
|
|
||||||
|
TIMESTAMP TimeSinceEpoch(void)
|
||||||
|
{
|
||||||
|
TIMESTAMP rc;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
rc = (tv.tv_sec * (TIMESTAMP)1000) + (tv.tv_usec / (TIMESTAMP)1000);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMESTAMP TimeSinceStart(void)
|
||||||
|
{
|
||||||
|
return TimeSinceEpoch() - start_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeInit(void)
|
||||||
|
{
|
||||||
|
start_timestamp = TimeSinceEpoch();
|
||||||
|
}
|
10
src/time_func.h
Normal file
10
src/time_func.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef __TIMEFUNC_H_INCLUDED
|
||||||
|
#define __TIMEFUNC_H_INCLUDED
|
||||||
|
|
||||||
|
#include "wintype.h"
|
||||||
|
|
||||||
|
extern TIMESTAMP TimeSinceEpoch(void);
|
||||||
|
extern TIMESTAMP TimeSinceStart(void);
|
||||||
|
extern void TimeInit(void);
|
||||||
|
|
||||||
|
#endif /* __TIMEFUNC_H_INCLUDED */
|
8
src/wintype.h
Normal file
8
src/wintype.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __WINTYPE_H_INCLUDED
|
||||||
|
#define __WINTYPE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint64_t TIMESTAMP;
|
||||||
|
|
||||||
|
#endif /* __WINTYPE_H_INCLUDED */
|
Loading…
Reference in New Issue
Block a user