diff --git a/src/config.c b/src/config.c index e940919..8aecc61 100644 --- a/src/config.c +++ b/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[]) diff --git a/src/config.h b/src/config.h index 4916612..3955d9c 100644 --- a/src/config.h +++ b/src/config.h @@ -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; diff --git a/src/main.c b/src/main.c index 414f931..b945f95 100644 --- a/src/main.c +++ b/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; } diff --git a/src/msg.h b/src/msg.h index d388e24..03f91c2 100644 --- a/src/msg.h +++ b/src/msg.h @@ -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 */ diff --git a/src/msg_queue.c b/src/msg_queue.c index fbe483e..61252ad 100644 --- a/src/msg_queue.c +++ b/src/msg_queue.c @@ -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); } diff --git a/src/msg_queue.h b/src/msg_queue.h index a5220a5..1ba3626 100644 --- a/src/msg_queue.h +++ b/src/msg_queue.h @@ -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 */ diff --git a/src/sysinput.c b/src/sysinput.c index 2cb2aff..dcec699 100644 --- a/src/sysinput.c +++ b/src/sysinput.c @@ -1,7 +1,11 @@ #include #include #include +#include +#include +#include #include +#include #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