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[] = {
|
static const struct option long_options[] = {
|
||||||
{"framebuffer", required_argument, 0, 'F'},
|
{"framebuffer", required_argument, 0, 'F'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"touchscreen", required_argument, 0, 'T'},
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *short_options = "F:h";
|
static const char *short_options = "F:hT:";
|
||||||
|
|
||||||
static const char *helptext =
|
static const char *helptext =
|
||||||
"UPIWIN - Micro Pi Windows server program\n\n"
|
"UPIWIN - Micro Pi Windows server program\n\n"
|
||||||
|
@ -21,6 +22,7 @@ static const char *helptext =
|
||||||
"Available options:\n"
|
"Available options:\n"
|
||||||
" -F,--framebuffer [devname] - Specifies the framebuffer device name\n"
|
" -F,--framebuffer [devname] - Specifies the framebuffer device name\n"
|
||||||
" -h,--help - Displays this help message.\n"
|
" -h,--help - Displays this help message.\n"
|
||||||
|
" -T,--touchscreen - Specifies the touchscreen device name\n"
|
||||||
"";
|
"";
|
||||||
|
|
||||||
#define EXITFUNCBLOCK_FUNCCOUNT 64
|
#define EXITFUNCBLOCK_FUNCCOUNT 64
|
||||||
|
@ -58,6 +60,7 @@ static void run_exit_funcs(void)
|
||||||
static void init_defaults(void)
|
static void init_defaults(void)
|
||||||
{
|
{
|
||||||
Gconfig.framebuffer_device = "/dev/fb1";
|
Gconfig.framebuffer_device = "/dev/fb1";
|
||||||
|
Gconfig.touchscreen_device = "/dev/input/touchscreen";
|
||||||
Gconfig.button_debounce = 100;
|
Gconfig.button_debounce = 100;
|
||||||
Gconfig.sys_mq_length = 64;
|
Gconfig.sys_mq_length = 64;
|
||||||
}
|
}
|
||||||
|
@ -92,6 +95,18 @@ static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed)
|
||||||
help = TRUE;
|
help = TRUE;
|
||||||
break;
|
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:
|
default:
|
||||||
fprintf(stderr, "%s: unexpected option -%c\n", argv[0], c);
|
fprintf(stderr, "%s: unexpected option -%c\n", argv[0], c);
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
@ -109,6 +124,8 @@ static void overlay_config(GLOBAL_CONFIG *p)
|
||||||
{
|
{
|
||||||
if (p->framebuffer_device)
|
if (p->framebuffer_device)
|
||||||
Gconfig.framebuffer_device = 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[])
|
HRESULT Config_setup(int argc, char *argv[])
|
||||||
|
|
|
@ -7,6 +7,7 @@ typedef void (*PEXITFUNC)(void);
|
||||||
|
|
||||||
typedef struct tagGLOBAL_CONFIG {
|
typedef struct tagGLOBAL_CONFIG {
|
||||||
PCSTR framebuffer_device;
|
PCSTR framebuffer_device;
|
||||||
|
PCSTR touchscreen_device;
|
||||||
UINT32 button_debounce;
|
UINT32 button_debounce;
|
||||||
UINT32 sys_mq_length;
|
UINT32 sys_mq_length;
|
||||||
} GLOBAL_CONFIG;
|
} 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);
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -77,6 +82,18 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,8 @@ typedef struct tagMSG {
|
||||||
#define WM_HWBUTTONDOWN 0x0020
|
#define WM_HWBUTTONDOWN 0x0020
|
||||||
#define WM_HWBUTTONUP 0x0021
|
#define WM_HWBUTTONUP 0x0021
|
||||||
|
|
||||||
|
#define WM_TOUCHDOWN 0x0030
|
||||||
|
#define WM_TOUCHMOVE 0x0031
|
||||||
|
#define WM_TOUCHUP 0x0032
|
||||||
|
|
||||||
#endif /* __MSG_H_INCLUDED */
|
#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);
|
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;
|
MSG tmpmsg;
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ void Mq_post1(PMSG_QUEUE queue, HANDLE target, UINT32 message, UINT_PTR attr1)
|
||||||
tmpmsg.target = target;
|
tmpmsg.target = target;
|
||||||
tmpmsg.message = message;
|
tmpmsg.message = message;
|
||||||
tmpmsg.attrs[0] = attr1;
|
tmpmsg.attrs[0] = attr1;
|
||||||
|
tmpmsg.attrs[1] = attr2;
|
||||||
tmpmsg.timestamp = Time_since_start();
|
tmpmsg.timestamp = Time_since_start();
|
||||||
post_internal(queue, &tmpmsg);
|
post_internal(queue, &tmpmsg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,10 @@ typedef struct tagMSG_QUEUE {
|
||||||
extern PMSG_QUEUE Mq_alloc(UINT32 nentries);
|
extern PMSG_QUEUE Mq_alloc(UINT32 nentries);
|
||||||
extern void Mq_destroy(PMSG_QUEUE queue);
|
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_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);
|
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 */
|
#endif /* __MSG_QUEUE_H_INCLUDED */
|
||||||
|
|
102
src/sysinput.c
102
src/sysinput.c
|
@ -1,7 +1,11 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <linux/input.h>
|
||||||
#include "scode.h"
|
#include "scode.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -9,23 +13,27 @@
|
||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
#include "time_func.h"
|
#include "time_func.h"
|
||||||
|
|
||||||
|
#define INPUT_EVENT_BATCH 16
|
||||||
|
|
||||||
PMSG_QUEUE Sys_Queue = NULL;
|
PMSG_QUEUE Sys_Queue = NULL;
|
||||||
|
|
||||||
static pthread_t ithread;
|
static pthread_t ithread;
|
||||||
static volatile sig_atomic_t running = 1;
|
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;
|
UINT32 st, down, up, mask;
|
||||||
UINT_PTR attr;
|
UINT_PTR attr;
|
||||||
TIMESTAMP now;
|
TIMESTAMP now;
|
||||||
TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT];
|
|
||||||
|
|
||||||
memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP));
|
|
||||||
|
|
||||||
while (running)
|
|
||||||
{
|
|
||||||
/* poll hardware buttons */
|
/* poll hardware buttons */
|
||||||
st = Gpio_read_buttons();
|
st = Gpio_read_buttons();
|
||||||
if (st != last_bstate)
|
if (st != last_bstate)
|
||||||
|
@ -47,8 +55,71 @@ static void *input_thread(void *arg)
|
||||||
}
|
}
|
||||||
last_bstate = st;
|
last_bstate = st;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* additional poll activity here */
|
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_buttons();
|
||||||
|
poll_touchscreen();
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +128,8 @@ static void do_disable_input(void)
|
||||||
{
|
{
|
||||||
running = 0;
|
running = 0;
|
||||||
pthread_join(ithread, NULL);
|
pthread_join(ithread, NULL);
|
||||||
|
close(ts_fd);
|
||||||
|
ts_fd = -1;
|
||||||
Mq_destroy(Sys_Queue);
|
Mq_destroy(Sys_Queue);
|
||||||
Sys_Queue = NULL;
|
Sys_Queue = NULL;
|
||||||
}
|
}
|
||||||
|
@ -72,11 +145,24 @@ HRESULT Sys_enable_input(void)
|
||||||
Log(LFATAL, "Unable to allocate system message queue.");
|
Log(LFATAL, "Unable to allocate system message queue.");
|
||||||
return E_OUTOFMEMORY;
|
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;
|
running = 1;
|
||||||
threadrc = pthread_create(&ithread, NULL, input_thread, NULL);
|
threadrc = pthread_create(&ithread, NULL, input_thread, NULL);
|
||||||
if (threadrc != 0)
|
if (threadrc != 0)
|
||||||
{
|
{
|
||||||
rc = SCODE_FROM_ERRNO(threadrc);
|
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);
|
Log(LFATAL, "Unable to start system input thread (%08X).", rc);
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(rc))
|
if (SUCCEEDED(rc))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user