implemented the touchscreen device events
This commit is contained in:
		
							parent
							
								
									0dc56d49e5
								
							
						
					
					
						commit
						dfe9991496
					
				
							
								
								
									
										19
									
								
								src/config.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/config.c
									
									
									
									
									
								
							@ -10,10 +10,11 @@
 | 
			
		||||
static const struct option long_options[] = {
 | 
			
		||||
  {"framebuffer", required_argument, 0, 'F'},
 | 
			
		||||
  {"help",        no_argument,       0, 'h'},
 | 
			
		||||
  {"touchscreen", required_argument, 0, 'T'},
 | 
			
		||||
  { NULL,         0,                 0,  0 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *short_options = "F:h";
 | 
			
		||||
static const char *short_options = "F:hT:";
 | 
			
		||||
 | 
			
		||||
static const char *helptext =
 | 
			
		||||
  "UPIWIN - Micro Pi Windows server program\n\n"
 | 
			
		||||
@ -21,6 +22,7 @@ static const char *helptext =
 | 
			
		||||
  "Available options:\n"
 | 
			
		||||
  "  -F,--framebuffer [devname] - Specifies the framebuffer device name\n"
 | 
			
		||||
  "  -h,--help - Displays this help message.\n"
 | 
			
		||||
  "  -T,--touchscreen - Specifies the touchscreen device name\n"
 | 
			
		||||
  "";
 | 
			
		||||
 | 
			
		||||
#define EXITFUNCBLOCK_FUNCCOUNT 64
 | 
			
		||||
@ -58,6 +60,7 @@ static void run_exit_funcs(void)
 | 
			
		||||
static void init_defaults(void)
 | 
			
		||||
{
 | 
			
		||||
  Gconfig.framebuffer_device = "/dev/fb1";
 | 
			
		||||
  Gconfig.touchscreen_device = "/dev/input/touchscreen";
 | 
			
		||||
  Gconfig.button_debounce = 100;
 | 
			
		||||
  Gconfig.sys_mq_length = 64;
 | 
			
		||||
}
 | 
			
		||||
@ -92,6 +95,18 @@ static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed)
 | 
			
		||||
	help = TRUE;
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
      case 'T':
 | 
			
		||||
	pstr = strdup(optarg);
 | 
			
		||||
	if (!pstr)
 | 
			
		||||
	{
 | 
			
		||||
	  Log(LERROR, "Out of memory in parse_cmdline");
 | 
			
		||||
	  return E_OUTOFMEMORY;
 | 
			
		||||
	}
 | 
			
		||||
	if (parsed->touchscreen_device)
 | 
			
		||||
	  free((PVOID)(parsed->touchscreen_device));
 | 
			
		||||
	parsed->touchscreen_device = pstr;
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
	fprintf(stderr, "%s: unexpected option -%c\n", argv[0], c);
 | 
			
		||||
	return E_UNEXPECTED;
 | 
			
		||||
@ -109,6 +124,8 @@ static void overlay_config(GLOBAL_CONFIG *p)
 | 
			
		||||
{
 | 
			
		||||
  if (p->framebuffer_device)
 | 
			
		||||
    Gconfig.framebuffer_device = p->framebuffer_device;
 | 
			
		||||
  if (p->touchscreen_device)
 | 
			
		||||
    Gconfig.touchscreen_device = p->touchscreen_device;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HRESULT Config_setup(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ typedef void (*PEXITFUNC)(void);
 | 
			
		||||
 | 
			
		||||
typedef struct tagGLOBAL_CONFIG {
 | 
			
		||||
  PCSTR framebuffer_device;
 | 
			
		||||
  PCSTR touchscreen_device;
 | 
			
		||||
  UINT32 button_debounce;
 | 
			
		||||
  UINT32 sys_mq_length;
 | 
			
		||||
} GLOBAL_CONFIG;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/main.c
									
									
									
									
									
								
							@ -20,6 +20,11 @@ static void do_draw(void)
 | 
			
		||||
  Fb_filled_rectangle(110, 60, 150, 100, FBPRIMCLR_YELLOW, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void log_touch(const char *event, UINT_PTR x, UINT_PTR y)
 | 
			
		||||
{
 | 
			
		||||
  Log(LINFO, "Touch %s at (%u, %u)", event, x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  HRESULT hr;
 | 
			
		||||
@ -77,6 +82,18 @@ int main(int argc, char *argv[])
 | 
			
		||||
	  }
 | 
			
		||||
	  break;
 | 
			
		||||
 | 
			
		||||
	case WM_TOUCHDOWN:
 | 
			
		||||
	  log_touch("DOWN", msg.attrs[0], msg.attrs[1]);
 | 
			
		||||
	  break;
 | 
			
		||||
	  
 | 
			
		||||
	case WM_TOUCHMOVE:
 | 
			
		||||
	  log_touch("MOVE", msg.attrs[0], msg.attrs[1]);
 | 
			
		||||
	  break;
 | 
			
		||||
	  
 | 
			
		||||
	case WM_TOUCHUP:
 | 
			
		||||
	  log_touch("UP", msg.attrs[0], msg.attrs[1]);
 | 
			
		||||
	  break;
 | 
			
		||||
	  
 | 
			
		||||
	default:
 | 
			
		||||
	  break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -17,4 +17,8 @@ typedef struct tagMSG {
 | 
			
		||||
#define WM_HWBUTTONDOWN   0x0020
 | 
			
		||||
#define WM_HWBUTTONUP     0x0021
 | 
			
		||||
 | 
			
		||||
#define WM_TOUCHDOWN      0x0030
 | 
			
		||||
#define WM_TOUCHMOVE      0x0031
 | 
			
		||||
#define WM_TOUCHUP        0x0032
 | 
			
		||||
 | 
			
		||||
#endif /* __MSG_H_INCLUDED */
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,7 @@ void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *at
 | 
			
		||||
  post_internal(queue, &tmpmsg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Mq_post1(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1)
 | 
			
		||||
void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2)
 | 
			
		||||
{
 | 
			
		||||
  MSG tmpmsg;
 | 
			
		||||
  
 | 
			
		||||
@ -69,6 +69,7 @@ void Mq_post1(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1)
 | 
			
		||||
  tmpmsg.target = target;
 | 
			
		||||
  tmpmsg.message = message;
 | 
			
		||||
  tmpmsg.attrs[0] = attr1;
 | 
			
		||||
  tmpmsg.attrs[1] = attr2;
 | 
			
		||||
  tmpmsg.timestamp = Time_since_start();
 | 
			
		||||
  post_internal(queue, &tmpmsg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,10 @@ typedef struct tagMSG_QUEUE {
 | 
			
		||||
extern PMSG_QUEUE Mq_alloc(UINT32 nentries);
 | 
			
		||||
extern void Mq_destroy(PMSG_QUEUE queue);
 | 
			
		||||
extern void Mq_post(PMSG_QUEUE queue, HANDLE target, UINT32 message, const UINT_PTR *attrs, int nattrs);
 | 
			
		||||
extern void Mq_post1(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1);
 | 
			
		||||
extern void Mq_post2(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1, UINT_PTR attr2);
 | 
			
		||||
extern BOOL Mq_peek(PMSG_QUEUE queue, PMSG msg, UINT32 flags);
 | 
			
		||||
 | 
			
		||||
#define Mq_post0(q, tgt, msg)         Mq_post2(q, tgt, msg, 0, 0)
 | 
			
		||||
#define Mq_post1(q, tgt, msg, attr)   Mq_post2(q, tgt, msg, attr, 0)
 | 
			
		||||
 | 
			
		||||
#endif /* __MSG_QUEUE_H_INCLUDED */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										138
									
								
								src/sysinput.c
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								src/sysinput.c
									
									
									
									
									
								
							@ -1,7 +1,11 @@
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <linux/input.h>
 | 
			
		||||
#include "scode.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
@ -9,46 +13,113 @@
 | 
			
		||||
#include "gpio.h"
 | 
			
		||||
#include "time_func.h"
 | 
			
		||||
 | 
			
		||||
#define INPUT_EVENT_BATCH 16
 | 
			
		||||
 | 
			
		||||
PMSG_QUEUE Sys_Queue = NULL;
 | 
			
		||||
 | 
			
		||||
static pthread_t ithread;
 | 
			
		||||
static volatile sig_atomic_t running = 1;
 | 
			
		||||
static UINT32 last_bstate = 0;
 | 
			
		||||
static int ts_fd = 0;
 | 
			
		||||
 | 
			
		||||
static void *input_thread(void *arg)
 | 
			
		||||
static UINT32 last_bstate = 0;
 | 
			
		||||
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT];
 | 
			
		||||
 | 
			
		||||
static UINT_PTR touch_x = 0;
 | 
			
		||||
static UINT_PTR touch_y = 0;
 | 
			
		||||
static UINT32 touch_nextmsg = WM_TOUCHMOVE;
 | 
			
		||||
 | 
			
		||||
static void poll_buttons(void)
 | 
			
		||||
{
 | 
			
		||||
  UINT32 st, down, up, mask;
 | 
			
		||||
  UINT_PTR attr;
 | 
			
		||||
  TIMESTAMP now;
 | 
			
		||||
  TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT];
 | 
			
		||||
 | 
			
		||||
  /* poll hardware buttons */
 | 
			
		||||
  st = Gpio_read_buttons();
 | 
			
		||||
  if (st != last_bstate)
 | 
			
		||||
  {
 | 
			
		||||
    now = Time_since_start();
 | 
			
		||||
    up = last_bstate & ~st;
 | 
			
		||||
    down = st & ~last_bstate;
 | 
			
		||||
    for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1)
 | 
			
		||||
    {
 | 
			
		||||
      if (now < button_event_ok[attr - 1])
 | 
			
		||||
	continue;
 | 
			
		||||
      if (up & mask)
 | 
			
		||||
      {
 | 
			
		||||
	button_event_ok[attr - 1] = now + Gconfig.button_debounce;
 | 
			
		||||
	Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
 | 
			
		||||
      }
 | 
			
		||||
      else if (down & mask)
 | 
			
		||||
	Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr);
 | 
			
		||||
    }
 | 
			
		||||
    last_bstate = st;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void poll_touchscreen(void)
 | 
			
		||||
{
 | 
			
		||||
  int nb, nev, xerrno, i;
 | 
			
		||||
  struct input_event buffer[INPUT_EVENT_BATCH];
 | 
			
		||||
 | 
			
		||||
  nb = read(ts_fd, buffer, INPUT_EVENT_BATCH * sizeof(struct input_event));
 | 
			
		||||
  if (nb == -1)
 | 
			
		||||
  {
 | 
			
		||||
    xerrno = errno;
 | 
			
		||||
    if ((xerrno != EAGAIN) && (xerrno != EWOULDBLOCK))
 | 
			
		||||
      Log(LERROR, "Error reading from touchscreen device (%d)", xerrno);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  else if (nb == 0)
 | 
			
		||||
  {
 | 
			
		||||
    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)
 | 
			
		||||
    {
 | 
			
		||||
      case EV_SYN:
 | 
			
		||||
	if (buffer[i].code == SYN_REPORT)
 | 
			
		||||
	{
 | 
			
		||||
	  Mq_post2(Sys_Queue, 0, touch_nextmsg, touch_x, touch_y);
 | 
			
		||||
	  touch_nextmsg = WM_TOUCHMOVE;
 | 
			
		||||
	}
 | 
			
		||||
	break;
 | 
			
		||||
	
 | 
			
		||||
      case EV_ABS:
 | 
			
		||||
	if (buffer[i].code == ABS_X)
 | 
			
		||||
	  touch_x = buffer[i].value;
 | 
			
		||||
	else if (buffer[i].code == ABS_Y)
 | 
			
		||||
	  touch_y = buffer[i].value;
 | 
			
		||||
	break;
 | 
			
		||||
	
 | 
			
		||||
      case EV_KEY:
 | 
			
		||||
	if (buffer[i].code == BTN_TOUCH)
 | 
			
		||||
	  touch_nextmsg = (buffer[i].value ? WM_TOUCHDOWN : WM_TOUCHUP);
 | 
			
		||||
	break;
 | 
			
		||||
	
 | 
			
		||||
      default:
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *input_thread(void *arg)
 | 
			
		||||
{
 | 
			
		||||
  last_bstate = 0;
 | 
			
		||||
  memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP));
 | 
			
		||||
  touch_x = touch_y = 0;
 | 
			
		||||
  touch_nextmsg = WM_TOUCHMOVE;
 | 
			
		||||
  
 | 
			
		||||
  while (running)
 | 
			
		||||
  {
 | 
			
		||||
    /* poll hardware buttons */
 | 
			
		||||
    st = Gpio_read_buttons();
 | 
			
		||||
    if (st != last_bstate)
 | 
			
		||||
    {
 | 
			
		||||
      now = Time_since_start();
 | 
			
		||||
      up = last_bstate & ~st;
 | 
			
		||||
      down = st & ~last_bstate;
 | 
			
		||||
      for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1)
 | 
			
		||||
      {
 | 
			
		||||
	if (now < button_event_ok[attr - 1])
 | 
			
		||||
	  continue;
 | 
			
		||||
	if (up & mask)
 | 
			
		||||
	{
 | 
			
		||||
	  button_event_ok[attr - 1] = now + Gconfig.button_debounce;
 | 
			
		||||
	  Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
 | 
			
		||||
	}
 | 
			
		||||
	else if (down & mask)
 | 
			
		||||
	  Mq_post1(Sys_Queue, 0, WM_HWBUTTONDOWN, attr);
 | 
			
		||||
      }
 | 
			
		||||
      last_bstate = st;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* additional poll activity here */
 | 
			
		||||
    poll_buttons();
 | 
			
		||||
    poll_touchscreen();
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
@ -57,6 +128,8 @@ static void do_disable_input(void)
 | 
			
		||||
{
 | 
			
		||||
  running = 0;
 | 
			
		||||
  pthread_join(ithread, NULL);
 | 
			
		||||
  close(ts_fd);
 | 
			
		||||
  ts_fd = -1;
 | 
			
		||||
  Mq_destroy(Sys_Queue);
 | 
			
		||||
  Sys_Queue = NULL;
 | 
			
		||||
}
 | 
			
		||||
@ -72,11 +145,24 @@ HRESULT Sys_enable_input(void)
 | 
			
		||||
    Log(LFATAL, "Unable to allocate system message queue.");
 | 
			
		||||
    return E_OUTOFMEMORY;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ts_fd = open(Gconfig.touchscreen_device, O_RDONLY|O_NONBLOCK);
 | 
			
		||||
  if (ts_fd < 0)
 | 
			
		||||
  {
 | 
			
		||||
    rc = ERRNO_AS_SCODE;
 | 
			
		||||
    Mq_destroy(Sys_Queue);
 | 
			
		||||
    Log(LFATAL, "Unable to open touchscreen device (%08X).", rc);
 | 
			
		||||
    return rc;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  running = 1;
 | 
			
		||||
  threadrc = pthread_create(&ithread, NULL, input_thread, NULL);
 | 
			
		||||
  if (threadrc != 0)
 | 
			
		||||
  {
 | 
			
		||||
    rc = SCODE_FROM_ERRNO(threadrc);
 | 
			
		||||
    close(ts_fd);
 | 
			
		||||
    ts_fd = -1;
 | 
			
		||||
    Mq_destroy(Sys_Queue);
 | 
			
		||||
    Log(LFATAL, "Unable to start system input thread (%08X).", rc);
 | 
			
		||||
  }
 | 
			
		||||
  if (SUCCEEDED(rc))
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user