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=
 | 
			
		||||
 | 
			
		||||
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 new_state = 0;
 | 
			
		||||
  int new_state = Gpio_read_buttons();
 | 
			
		||||
  int tmp, ndx, mask;
 | 
			
		||||
  
 | 
			
		||||
  if (gpio_input(GLINE_BUTTON1) == 0)
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
extern int Gpio_setup(void);
 | 
			
		||||
extern void Gpio_cleanup(void);
 | 
			
		||||
extern int Gpio_read_buttons(void);
 | 
			
		||||
extern int Gpio_poll_buttons(void);
 | 
			
		||||
 | 
			
		||||
#endif /* __GPIO_H_INCLUDED */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								src/main.c
									
									
									
									
									
								
							@ -1,16 +1,42 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "gpio.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "time_func.h"
 | 
			
		||||
#include "sysinput.h"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  MSG msg;
 | 
			
		||||
  
 | 
			
		||||
  TimeInit();
 | 
			
		||||
  if (Gpio_setup() != 0)
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  atexit(Gpio_cleanup);
 | 
			
		||||
  if (SysEnableInput() != 0)
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  atexit(SysDisableInput);
 | 
			
		||||
 | 
			
		||||
  Log(LINFO, "System ready.");
 | 
			
		||||
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    Gpio_poll_buttons();
 | 
			
		||||
  for (;;)
 | 
			
		||||
  {
 | 
			
		||||
    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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user