From 3b06b9d54bad55ed6df415b8860df0b90c6558da Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 07:54:32 -0400 Subject: [PATCH 01/14] Remove best vendor == USB_VID_GOO check, this is insufficient for checking that we are in OAP/AA mode and breaks a Nexus device Signed-off-by: Matt Porter --- jni/hu_usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jni/hu_usb.c b/jni/hu_usb.c index 1b1a03df..eea69d0f 100644 --- a/jni/hu_usb.c +++ b/jni/hu_usb.c @@ -636,6 +636,7 @@ int LIBUSB_CALL libusb_bulk_transfer (libusb_device_handle *dev_han } logd ("OK iusb_init"); +#if 0 if (iusb_best_vendor == USB_VID_GOO) { logd ("Already OAP/AA mode, no need to call iusb_oap_start()"); @@ -643,6 +644,7 @@ int LIBUSB_CALL libusb_bulk_transfer (libusb_device_handle *dev_han logd (" SET: iusb_state: %d (%s)", iusb_state, state_get (iusb_state)); return (0); } +#endif ret = iusb_oap_start (); if (ret < 0) { From 6736834f1d525e0ae9184f9a4ec19ac6e4319576 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 08:12:15 -0400 Subject: [PATCH 02/14] Add a repo .gitignore to avoid noise in git commands Signed-off-by: Matt Porter --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5761abcf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o From 335205046c99cc74a83073d7af5903329cbd1a29 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 08:13:37 -0400 Subject: [PATCH 03/14] Add additional extern references to fix implicit declaration warnings in build Signed-off-by: Matt Porter --- jni/hu_aap.c | 2 ++ jni/hu_ssl.c | 1 + jni/hu_ssl.h | 1 + jni/hu_usb.c | 1 + jni/hu_usb.h | 10 +++++----- jni/hu_uti.c | 1 + jni/hu_uti.h | 5 +++++ 7 files changed, 16 insertions(+), 5 deletions(-) diff --git a/jni/hu_aap.c b/jni/hu_aap.c index 420a82e2..9452f73b 100644 --- a/jni/hu_aap.c +++ b/jni/hu_aap.c @@ -2,8 +2,10 @@ // Android Auto Protocol Handler #define LOGTAG "hu_aap" + #include "hu_usb.h" #include "hu_uti.h" #include "hu_ssl.h" + #include "hu_aap.h" #ifndef NDEBUG #include "hu_aad.h" #endif diff --git a/jni/hu_ssl.c b/jni/hu_ssl.c index 0a9e2c17..6b24fd46 100644 --- a/jni/hu_ssl.c +++ b/jni/hu_ssl.c @@ -4,6 +4,7 @@ #include "hu_aap.h" #include + #include #include #include #include diff --git a/jni/hu_ssl.h b/jni/hu_ssl.h index fc0557cc..d69b7495 100644 --- a/jni/hu_ssl.h +++ b/jni/hu_ssl.h @@ -13,6 +13,7 @@ extern BIO * hu_ssl_wm_bio;// = NULL; void hu_ssl_ret_log (int ret); + extern void hu_ssl_inf_log (void); int hu_ssl_handshake (); diff --git a/jni/hu_usb.c b/jni/hu_usb.c index eea69d0f..aad20983 100644 --- a/jni/hu_usb.c +++ b/jni/hu_usb.c @@ -4,6 +4,7 @@ #define LOGTAG "hu_usb" #include "hu_uti.h" // Utilities #include "hu_oap.h" // Open Accessory Protocol + #include "hu_usb.h" int iusb_state = 0; // 0: Initial 1: Startin 2: Started 3: Stoppin 4: Stopped diff --git a/jni/hu_usb.h b/jni/hu_usb.h index 4e2862cf..7a6adbc2 100644 --- a/jni/hu_usb.h +++ b/jni/hu_usb.h @@ -1,6 +1,6 @@ +#include "hu_uti.h" - int hu_usb_recv (byte * buf, int len, int tmo); // Used by hu_aap:hu_aap_usb_recv () - int hu_usb_send (byte * buf, int len, int tmo); // Used by hu_aap:hu_aap_usb_send () - int hu_usb_stop (); // Used by hu_aap:hu_aap_stop () - int hu_usb_start (byte ep_in_addr, byte ep_out_addr); // Used by hu_aap:hu_aap_start () - + extern int hu_usb_recv (byte * buf, int len, int tmo); // Used by hu_aap:hu_aap_usb_recv () + extern int hu_usb_send (byte * buf, int len, int tmo); // Used by hu_aap:hu_aap_usb_send () + extern int hu_usb_stop (); // Used by hu_aap:hu_aap_stop () + extern int hu_usb_start (byte ep_in_addr, byte ep_out_addr); // Used by hu_aap:hu_aap_start () diff --git a/jni/hu_uti.c b/jni/hu_uti.c index bf82e0e6..c4d13951 100644 --- a/jni/hu_uti.c +++ b/jni/hu_uti.c @@ -28,6 +28,7 @@ } #endif + #include #include #include #include diff --git a/jni/hu_uti.h b/jni/hu_uti.h index 5f2ab160..50a150be 100644 --- a/jni/hu_uti.h +++ b/jni/hu_uti.h @@ -34,6 +34,11 @@ extern int ena_log_verbo; extern int ena_log_send; + extern char * state_get (int); + extern int file_get (const char *); + + int insmod_internal (const char *); + #define byte unsigned char #define DEFBUF 65536 //16384 // Default buffer size is maximum for USB From b29144447022f73c3ff5bad9f76a55e3452ea861 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 08:18:11 -0400 Subject: [PATCH 04/14] Add initial working gstreamer headunit app Signed-off-by: Matt Porter --- gst/Makefile | 30 ++++++ gst/main.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+) create mode 100644 gst/Makefile create mode 100644 gst/main.c diff --git a/gst/Makefile b/gst/Makefile new file mode 100644 index 00000000..1795c768 --- /dev/null +++ b/gst/Makefile @@ -0,0 +1,30 @@ +CC=gcc +CFLAGS=`pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0 libcrypto libusb-1.0 openssl` -I$(TOP)/jni +LFLAGS=`pkg-config --libs gstreamer-1.0 gstreamer-app-1.0 libcrypto libusb-1.0 openssl` +TOP = .. +AASRCS = $(TOP)/jni/hu_aad.c \ + $(TOP)/jni/hu_aap.c \ + $(TOP)/jni/hu_ssl.c \ + $(TOP)/jni/hu_usb.c \ + $(TOP)/jni/hu_uti.c +SRCS = $(AASRCS) main.c +OBJS = $(SRCS:.c=.o) +APP = headunit + +.PHONY: depend clean + +all: $(APP) + +$(APP): $(OBJS) + $(CC) $(CFLAGS) -o $(APP) $(OBJS) $(LFLAGS) + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) *~ $(APP) + +depend: $(SRCS) + makedepend $^ + +# DO NOT DELETE diff --git a/gst/main.c b/gst/main.c new file mode 100644 index 00000000..c5fb5fd5 --- /dev/null +++ b/gst/main.c @@ -0,0 +1,268 @@ +#include +#include +#include +#define LOGTAG "hu_mai" +#include "hu_uti.h" +#include "hu_aap.h" + + +typedef struct { + GstPipeline *pipeline; + GstAppSrc *src; + GstElement *sink; + GstElement *decoder; + GstElement *convert; + GstElement *autovideosink; + GMainLoop *loop; + guint sourceid; +} gst_app_t; + +static gst_app_t gst_app; + +static gboolean read_data(gst_app_t *app) +{ + GstBuffer *buffer; + guint8 *ptr; + GstFlowReturn ret; + int iret; + + iret = hu_aap_recv_process (); // Process 1 message + if (iret != 0) { + loge("hu_aap_recv_process() iret: %d", iret); + return FALSE; + } + logd("hu_aap_recv_process() ret: %d", iret); + + /* Is there a buffer queued? */ + int res_len = 0; + byte * dq_buf = read_head_buffer_get (& res_len); + if (dq_buf != NULL) { + logd("dq_buf: %p res_len: %d", dq_buf, res_len); + + ptr= g_malloc(res_len); + g_assert(ptr); + memcpy(ptr, dq_buf, res_len); + + { + int i; + for (i=0; i<6; i++) + printf("buf[%d]: %08x\n", i, *((int *)ptr + i)); + } + buffer = gst_buffer_new_wrapped(ptr, res_len); + + ret = gst_app_src_push_buffer(app->src, buffer); + + if(ret != GST_FLOW_OK){ + g_debug("push buffer returned %d for %d bytes \n", ret, res_len); + return FALSE; + } + +#if 0 + if(size != BUFF_SIZE){ + ret = gst_app_src_end_of_stream(app->src); + g_debug("eos returned %d at %d\n", ret, __LINE__); + return FALSE; + } +#endif + } + + return TRUE; +} + +static void start_feed (GstElement * pipeline, guint size, gst_app_t *app) +{ + printf("app->sourceid = %d\n", app->sourceid); + if (app->sourceid == 0) { + GST_DEBUG ("start feeding"); + app->sourceid = g_idle_add ((GSourceFunc) read_data, app); + } +} + +static void stop_feed (GstElement * pipeline, gst_app_t *app) +{ + if (app->sourceid != 0) { + GST_DEBUG ("stop feeding"); + g_source_remove (app->sourceid); + app->sourceid = 0; + } +} + +static void on_pad_added(GstElement *element, GstPad *pad) +{ + GstCaps *caps; + GstStructure *str; + gchar *name; + GstPad *convertsink; + GstPadLinkReturn ret; + + g_debug("pad added"); + + caps = gst_pad_get_current_caps(pad); + str = gst_caps_get_structure(caps, 0); + + g_assert(str); + + name = (gchar*)gst_structure_get_name(str); + + g_debug("pad name %s", name); + + if(g_strrstr(name, "video")){ + + convertsink = gst_element_get_static_pad(gst_app.convert, "sink"); + g_assert(convertsink); + ret = gst_pad_link(pad, convertsink); + g_debug("pad_link returned %d\n", ret); + gst_object_unref(convertsink); + } + gst_caps_unref(caps); +} + +static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr) +{ + gst_app_t *app = (gst_app_t*)ptr; + + switch(GST_MESSAGE_TYPE(message)){ + + case GST_MESSAGE_ERROR:{ + gchar *debug; + GError *err; + + gst_message_parse_error(message, &err, &debug); + g_print("Error %s\n", err->message); + g_error_free(err); + g_free(debug); + g_main_loop_quit(app->loop); + } + break; + + case GST_MESSAGE_WARNING:{ + gchar *debug; + GError *err; + gchar *name; + + gst_message_parse_warning(message, &err, &debug); + g_print("Warning %s\nDebug %s\n", err->message, debug); + + name = GST_MESSAGE_SRC_NAME(message); + + g_print("Name of src %s\n", name ? name : "nil"); + g_error_free(err); + g_free(debug); + } + break; + + case GST_MESSAGE_EOS: + g_print("End of stream\n"); + g_main_loop_quit(app->loop); + break; + + case GST_MESSAGE_STATE_CHANGED: + break; + + default: + g_print("got message %s\n", \ + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + break; + } + + return TRUE; +} + +static int gst_pipeline_init(gst_app_t *app) +{ + GstBus *bus; + GstStateChangeReturn state_ret; + + gst_init(NULL, NULL); + + app->pipeline = (GstPipeline*)gst_pipeline_new("mypipeline"); + bus = gst_pipeline_get_bus(app->pipeline); + gst_bus_add_watch(bus, (GstBusFunc)bus_callback, app); + gst_object_unref(bus); + + app->src = (GstAppSrc*)gst_element_factory_make("appsrc", "mysrc"); + app->decoder = gst_element_factory_make("decodebin", "mydecoder"); + app->convert = gst_element_factory_make("videoconvert", "myconvert"); + app->autovideosink = gst_element_factory_make("autovideosink", "myvsink"); + + g_assert(app->src); + g_assert(app->decoder); + g_assert(app->convert); + g_assert(app->autovideosink); + + g_signal_connect(app->src, "need-data", G_CALLBACK(start_feed), app); + g_signal_connect(app->src, "enough-data", G_CALLBACK(stop_feed), app); + g_signal_connect(app->decoder, "pad-added", + G_CALLBACK(on_pad_added), app->decoder); + + gst_bin_add_many(GST_BIN(app->pipeline), (GstElement*)app->src, + app->decoder, app->convert, app->autovideosink, NULL); + + if(!gst_element_link((GstElement*)app->src, app->decoder)){ + g_warning("failed to link src anbd decoder"); + } + + if(!gst_element_link(app->convert, app->autovideosink)){ + g_warning("failed to link convert and xvsink"); + } + + gst_app_src_set_stream_type(app->src, GST_APP_STREAM_TYPE_STREAM); + + return 0; +} + +static int gst_loop(gst_app_t *app) +{ + GstStateChangeReturn state_ret; + + state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_PLAYING); + g_warning("set state returned %d\n", state_ret); + + app->loop = g_main_loop_new(NULL, FALSE); + + g_main_loop_run(app->loop); + + state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_NULL); + g_warning("set state null returned %d\n", state_ret); + + return 0; +} + +int main (int argc, char *argv[]) +{ + gst_app_t *app = &gst_app; + int ret = 0; + errno = 0; + byte ep_in_addr = -1; + byte ep_out_addr = -1; + + /* Init gstreamer pipelien */ + ret = gst_pipeline_init(app); + if (ret < 0) { + loge("gst_pipeline_init() ret: %d", ret); + return (ret); + } + + /* Start AA processing */ + ret = hu_aap_start (ep_in_addr, ep_out_addr); + if (ret < 0) { + loge("hu_app_start() ret: %d", ret); + return (ret); + } + + /* Start gstreamer pipeline and main loop */ + ret = gst_loop(app); + if (ret < 0) { + loge("gst_loop() ret: %d", ret); + return (ret); + } + + /* Stop AA processing */ + ret = hu_aap_stop (); + if (ret < 0) { + loge("hu_aap_stop() ret: %d", ret); + return (ret); + } + + return (ret); +} From 12029dc931b15b133cd40282020097a9a14f5d49 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 08:40:43 -0400 Subject: [PATCH 05/14] add gst/headunit to gitignore Signed-off-by: Matt Porter --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5761abcf..1d0b183d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.o +headunit From fd6227cde9dabdf77dacb84ba54986b754ea2347 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 09:09:30 -0400 Subject: [PATCH 06/14] gst headunit app debug and variable cleanups Signed-off-by: Matt Porter --- gst/main.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/gst/main.c b/gst/main.c index c5fb5fd5..cb7bbf16 100644 --- a/gst/main.c +++ b/gst/main.c @@ -1,7 +1,6 @@ #include #include #include -#define LOGTAG "hu_mai" #include "hu_uti.h" #include "hu_aap.h" @@ -25,29 +24,24 @@ static gboolean read_data(gst_app_t *app) guint8 *ptr; GstFlowReturn ret; int iret; + char *vbuf; + int res_len = 0; iret = hu_aap_recv_process (); // Process 1 message if (iret != 0) { - loge("hu_aap_recv_process() iret: %d", iret); + printf("hu_aap_recv_process() iret: %d\n", iret); return FALSE; } - logd("hu_aap_recv_process() ret: %d", iret); - /* Is there a buffer queued? */ - int res_len = 0; - byte * dq_buf = read_head_buffer_get (& res_len); - if (dq_buf != NULL) { - logd("dq_buf: %p res_len: %d", dq_buf, res_len); + /* Is there a video buffer queued? */ + vbuf = read_head_buffer_get (& res_len); + if (vbuf != NULL) { + printf("vbuf: %p res_len: %d\n", vbuf, res_len); ptr= g_malloc(res_len); g_assert(ptr); - memcpy(ptr, dq_buf, res_len); + memcpy(ptr, vbuf, res_len); - { - int i; - for (i=0; i<6; i++) - printf("buf[%d]: %08x\n", i, *((int *)ptr + i)); - } buffer = gst_buffer_new_wrapped(ptr, res_len); ret = gst_app_src_push_buffer(app->src, buffer); @@ -71,7 +65,6 @@ static gboolean read_data(gst_app_t *app) static void start_feed (GstElement * pipeline, guint size, gst_app_t *app) { - printf("app->sourceid = %d\n", app->sourceid); if (app->sourceid == 0) { GST_DEBUG ("start feeding"); app->sourceid = g_idle_add ((GSourceFunc) read_data, app); @@ -239,28 +232,28 @@ int main (int argc, char *argv[]) /* Init gstreamer pipelien */ ret = gst_pipeline_init(app); if (ret < 0) { - loge("gst_pipeline_init() ret: %d", ret); + printf("gst_pipeline_init() ret: %d\n", ret); return (ret); } /* Start AA processing */ ret = hu_aap_start (ep_in_addr, ep_out_addr); if (ret < 0) { - loge("hu_app_start() ret: %d", ret); + printf("hu_app_start() ret: %d\n", ret); return (ret); } /* Start gstreamer pipeline and main loop */ ret = gst_loop(app); if (ret < 0) { - loge("gst_loop() ret: %d", ret); + printf("gst_loop() ret: %d\n", ret); return (ret); } /* Stop AA processing */ ret = hu_aap_stop (); if (ret < 0) { - loge("hu_aap_stop() ret: %d", ret); + printf("hu_aap_stop() ret: %d\n", ret); return (ret); } From b6d8e387f567bcc3a5ab2b058fc8e9f3c56d5e9d Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 14:50:01 -0400 Subject: [PATCH 07/14] Make AA calls available to C++ Signed-off-by: Matt Porter --- gst/{main.c => main.cc} | 0 jni/hu_aap.h | 12 +++++++++--- jni/hu_uti.h | 8 +++++++- 3 files changed, 16 insertions(+), 4 deletions(-) rename gst/{main.c => main.cc} (100%) diff --git a/gst/main.c b/gst/main.cc similarity index 100% rename from gst/main.c rename to gst/main.cc diff --git a/jni/hu_aap.h b/jni/hu_aap.h index 90f39572..be1b48b4 100644 --- a/jni/hu_aap.h +++ b/jni/hu_aap.h @@ -3,11 +3,17 @@ int hu_aap_usb_set (int chan, int flags, int type, byte * buf, int len);// Used by intern hu_ssl int hu_aap_usb_send (byte * buf, int len, int tmo); // Used by intern, hu_ssl int hu_aap_enc_send (int chan, byte * buf, int len); // Used by intern, hu_jni // Encrypted Send - int hu_aap_stop (); // Used by hu_mai, hu_jni // NEED: Send Byebye, Stops USB/ACC/OAP - int hu_aap_start (byte ep_in_addr, byte ep_out_addr); // Used by hu_mai, hu_jni // Starts USB/ACC/OAP, then AA protocol w/ VersReq(1), SSL handshake, Auth Complete - int hu_aap_recv_process (); // Used by hu_mai, hu_jni // Process 1 encrypted receive message set: +#if defined (__cplusplus) + extern "C" { +#endif + extern int hu_aap_stop (); // Used by hu_mai, hu_jni // NEED: Send Byebye, Stops USB/ACC/OAP + extern int hu_aap_start (byte ep_in_addr, byte ep_out_addr); // Used by hu_mai, hu_jni // Starts USB/ACC/OAP, then AA protocol w/ VersReq(1), SSL handshake, Auth Complete + extern int hu_aap_recv_process (); // Used by hu_mai, hu_jni // Process 1 encrypted receive message set: // Read encrypted message from USB // Respond to decrypted message // If video data, put on queue +#if defined (__cplusplus) + } +#endif diff --git a/jni/hu_uti.h b/jni/hu_uti.h index 50a150be..fcc38433 100644 --- a/jni/hu_uti.h +++ b/jni/hu_uti.h @@ -90,7 +90,13 @@ unsigned long ms_sleep (unsigned long ms); void hex_dump (char * prefix, int width, unsigned char * buf, int len); char * write_tail_buffer_get (int len); - char * read_head_buffer_get (int * len); +#if defined (__cplusplus) + extern "C" { +#endif + extern char * read_head_buffer_get (int * len); +#if defined (__cplusplus) + } +#endif #ifndef __ANDROID_API__ #define strlcpy strncpy From 334e96b5882a19defad779f8955d76a0454f8b10 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 28 Sep 2015 14:51:10 -0400 Subject: [PATCH 08/14] Add support for gstreamer sinking to a Qt instantiated window to support mouse events Signed-off-by: Matt Porter --- gst/Makefile | 19 +++++++++---- gst/main.cc | 78 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/gst/Makefile b/gst/Makefile index 1795c768..ea5dd49e 100644 --- a/gst/Makefile +++ b/gst/Makefile @@ -1,14 +1,18 @@ CC=gcc -CFLAGS=`pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0 libcrypto libusb-1.0 openssl` -I$(TOP)/jni -LFLAGS=`pkg-config --libs gstreamer-1.0 gstreamer-app-1.0 libcrypto libusb-1.0 openssl` +CPP=g++ +LD=ld +INCLUDES=`pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0 gstreamer-video-1.0 libcrypto libusb-1.0 openssl` -I$(TOP)/jni -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtGui +CFLAGS= +CPPFLAGS=-fPIC +LFLAGS=`pkg-config --libs gstreamer-1.0 gstreamer-app-1.0 gstreamer-video-1.0 libcrypto libusb-1.0 openssl` -lQt5Core -lQt5Widgets -lQt5Gui TOP = .. AASRCS = $(TOP)/jni/hu_aad.c \ $(TOP)/jni/hu_aap.c \ $(TOP)/jni/hu_ssl.c \ $(TOP)/jni/hu_usb.c \ $(TOP)/jni/hu_uti.c -SRCS = $(AASRCS) main.c -OBJS = $(SRCS:.c=.o) +HSRCS = main.cc +OBJS = $(AASRCS:.c=.o) $(HSRCS:.cc=.o) APP = headunit .PHONY: depend clean @@ -16,10 +20,13 @@ APP = headunit all: $(APP) $(APP): $(OBJS) - $(CC) $(CFLAGS) -o $(APP) $(OBJS) $(LFLAGS) + $(CPP) -o $(APP) $(OBJS) $(LFLAGS) .c.o: - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +.cc.o: + $(CPP) $(CPPFLAGS) $(INCLUDES) -c $< -o $@ clean: rm -f $(OBJS) *~ $(APP) diff --git a/gst/main.cc b/gst/main.cc index cb7bbf16..ddac260e 100644 --- a/gst/main.cc +++ b/gst/main.cc @@ -1,18 +1,23 @@ +#include #include #include #include +#include +#include +//#include +#include +#include + + #include "hu_uti.h" #include "hu_aap.h" - typedef struct { GstPipeline *pipeline; GstAppSrc *src; GstElement *sink; GstElement *decoder; GstElement *convert; - GstElement *autovideosink; - GMainLoop *loop; guint sourceid; } gst_app_t; @@ -38,7 +43,7 @@ static gboolean read_data(gst_app_t *app) if (vbuf != NULL) { printf("vbuf: %p res_len: %d\n", vbuf, res_len); - ptr= g_malloc(res_len); + ptr = (guint8 *)g_malloc(res_len); g_assert(ptr); memcpy(ptr, vbuf, res_len); @@ -124,7 +129,7 @@ static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr) g_print("Error %s\n", err->message); g_error_free(err); g_free(debug); - g_main_loop_quit(app->loop); +// g_main_loop_quit(app->loop); } break; @@ -136,7 +141,7 @@ static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr) gst_message_parse_warning(message, &err, &debug); g_print("Warning %s\nDebug %s\n", err->message, debug); - name = GST_MESSAGE_SRC_NAME(message); + name = (gchar *)GST_MESSAGE_SRC_NAME(message); g_print("Name of src %s\n", name ? name : "nil"); g_error_free(err); @@ -146,7 +151,7 @@ static gboolean bus_callback(GstBus *bus, GstMessage *message, gpointer *ptr) case GST_MESSAGE_EOS: g_print("End of stream\n"); - g_main_loop_quit(app->loop); +// g_main_loop_quit(app->loop); break; case GST_MESSAGE_STATE_CHANGED: @@ -176,27 +181,27 @@ static int gst_pipeline_init(gst_app_t *app) app->src = (GstAppSrc*)gst_element_factory_make("appsrc", "mysrc"); app->decoder = gst_element_factory_make("decodebin", "mydecoder"); app->convert = gst_element_factory_make("videoconvert", "myconvert"); - app->autovideosink = gst_element_factory_make("autovideosink", "myvsink"); + app->sink = gst_element_factory_make("xvimagesink", "myvsink"); g_assert(app->src); g_assert(app->decoder); g_assert(app->convert); - g_assert(app->autovideosink); + g_assert(app->sink); g_signal_connect(app->src, "need-data", G_CALLBACK(start_feed), app); g_signal_connect(app->src, "enough-data", G_CALLBACK(stop_feed), app); - g_signal_connect(app->decoder, "pad-added", + g_signal_connect(app->decoder, "pad-added", G_CALLBACK(on_pad_added), app->decoder); - gst_bin_add_many(GST_BIN(app->pipeline), (GstElement*)app->src, - app->decoder, app->convert, app->autovideosink, NULL); + gst_bin_add_many(GST_BIN(app->pipeline), (GstElement*)app->src, + app->decoder, app->convert, app->sink, NULL); if(!gst_element_link((GstElement*)app->src, app->decoder)){ g_warning("failed to link src anbd decoder"); } - if(!gst_element_link(app->convert, app->autovideosink)){ - g_warning("failed to link convert and xvsink"); + if(!gst_element_link(app->convert, app->sink)){ + g_warning("failed to link convert and sink"); } gst_app_src_set_stream_type(app->src, GST_APP_STREAM_TYPE_STREAM); @@ -204,23 +209,41 @@ static int gst_pipeline_init(gst_app_t *app) return 0; } -static int gst_loop(gst_app_t *app) +static int gst_loop(gst_app_t *app, QApplication *qapp) { + int ret; GstStateChangeReturn state_ret; state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_PLAYING); g_warning("set state returned %d\n", state_ret); - app->loop = g_main_loop_new(NULL, FALSE); - - g_main_loop_run(app->loop); + ret = qapp->exec(); state_ret = gst_element_set_state((GstElement*)app->pipeline, GST_STATE_NULL); g_warning("set state null returned %d\n", state_ret); - return 0; + gst_object_unref(app->pipeline); + + return ret; } +class HuMainWindow: public QMainWindow +{ + public: + HuMainWindow() + {}; + ~ HuMainWindow(){}; + + void mouseReleaseEvent ( QMouseEvent * event ) + { + if(event->button() == Qt::LeftButton) { + printf("\n***\n"); + printf("YOU CLICKED MOUSE AT X:%d, Y:%d\n", event->x(), event->y()); + printf("***\n"); + } + }; +}; + int main (int argc, char *argv[]) { gst_app_t *app = &gst_app; @@ -229,6 +252,14 @@ int main (int argc, char *argv[]) byte ep_in_addr = -1; byte ep_out_addr = -1; + /* Init Qt window */ + QApplication qapp(argc, argv); + qapp.connect(&qapp, SIGNAL(lastWindowClosed()), &qapp, SLOT(quit ())); + + HuMainWindow *window = new HuMainWindow(); + window->resize(800, 480); + window->show(); + /* Init gstreamer pipelien */ ret = gst_pipeline_init(app); if (ret < 0) { @@ -236,6 +267,10 @@ int main (int argc, char *argv[]) return (ret); } + /* Overlay gst sink on the Qt window */ + WId xwinid = window->winId(); + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(app->sink), xwinid); + /* Start AA processing */ ret = hu_aap_start (ep_in_addr, ep_out_addr); if (ret < 0) { @@ -244,12 +279,15 @@ int main (int argc, char *argv[]) } /* Start gstreamer pipeline and main loop */ - ret = gst_loop(app); + ret = gst_loop(app, &qapp); if (ret < 0) { printf("gst_loop() ret: %d\n", ret); return (ret); } + /* Shut down window */ + window->hide(); + /* Stop AA processing */ ret = hu_aap_stop (); if (ret < 0) { From 31278e4ce9583551fac64a2d897b58cab6ff71e5 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 29 Sep 2015 14:52:16 -0400 Subject: [PATCH 09/14] extern hu_aap_enc_send for touchscreen events Signed-off-by: Matt Porter --- jni/hu_aap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jni/hu_aap.h b/jni/hu_aap.h index be1b48b4..f26abac7 100644 --- a/jni/hu_aap.h +++ b/jni/hu_aap.h @@ -2,10 +2,10 @@ int hu_aap_usb_recv (byte * buf, int len, int tmo); // Used by intern, hu_ssl int hu_aap_usb_set (int chan, int flags, int type, byte * buf, int len);// Used by intern hu_ssl int hu_aap_usb_send (byte * buf, int len, int tmo); // Used by intern, hu_ssl - int hu_aap_enc_send (int chan, byte * buf, int len); // Used by intern, hu_jni // Encrypted Send #if defined (__cplusplus) extern "C" { #endif + extern int hu_aap_enc_send (int chan, byte * buf, int len); // Used by intern, hu_jni // Encrypted Send extern int hu_aap_stop (); // Used by hu_mai, hu_jni // NEED: Send Byebye, Stops USB/ACC/OAP extern int hu_aap_start (byte ep_in_addr, byte ep_out_addr); // Used by hu_mai, hu_jni // Starts USB/ACC/OAP, then AA protocol w/ VersReq(1), SSL handshake, Auth Complete extern int hu_aap_recv_process (); // Used by hu_mai, hu_jni // Process 1 encrypted receive message set: From ff62aed3800750c4e0ab6a08fb9621bfe5060b16 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 29 Sep 2015 14:55:11 -0400 Subject: [PATCH 10/14] gst: add working touchscreen event support Signed-off-by: Matt Porter --- gst/main.cc | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) diff --git a/gst/main.cc b/gst/main.cc index ddac260e..eb8fd75c 100644 --- a/gst/main.cc +++ b/gst/main.cc @@ -4,7 +4,6 @@ #include #include #include -//#include #include #include @@ -227,6 +226,122 @@ static int gst_loop(gst_app_t *app, QApplication *qapp) return ret; } +static int aa_cmd_send(int cmd_len, unsigned char *cmd_buf, int res_max, unsigned char *res_buf) +{ + int chan = cmd_buf[0]; + int res_len = 0; + int ret = 0; + char *dq_buf; + + res_buf = (unsigned char *)malloc(res_max); + if (!res_buf) { + printf("TOTAL FAIL\n"); + return -1; + } + + printf("chan: %d cmd_len: %d\n", chan, cmd_len); + ret = hu_aap_enc_send (chan, cmd_buf+4, cmd_len - 4); + if (ret < 0) { + printf("aa_cmd_send(): hu_aap_enc_send() failed with (%d)\n", ret); + return ret; + } + + dq_buf = read_head_buffer_get(&res_len); + if (!dq_buf || res_len <= 0) { + printf("No data dq_buf!\n"); + return 0; + } + memcpy(res_buf, dq_buf, res_len); + /* FIXME - we do nothing with this crap, probably check for ack and move along */ + + free(res_buf); + + return res_len; +} + +static int varint_encode_long (long val, unsigned char *ba, int idx) +{ + if (val >= 0x7fffffffffffffffL) { + printf("Too big"); + return 1; + } + long left = val; + for (int idx2 = 0; idx2 < 9; idx2 ++) { + ba[idx+idx2] = (char)(0x7f & left); + left = left >> 7; + if (left == 0) { + return idx2 + 1; + } + else if (idx2 < 9 - 1) { + ba [idx+idx2] |= 0x80; + } + } + return 9; +} + +static int varint_encode_int(int val, unsigned char *ba, int idx) +{ + if (val >= 1 << 14) { + printf("Too big"); + return 1; + } + ba [idx+0] = (char)(0x7f & (val >> 0)); + ba [idx+1] = (char)(0x7f & (val >> 7)); + if (ba [idx+1] != 0) { + ba [idx+0] |= 0x80; + return 2; + } + return 1; +} + +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_MOVE 2 + +static void aa_touch (byte action, int x, int y) { + struct timespec tp; + + //0 1 - 9 10 X: 15, 16 Y: 18, 19 25 + unsigned char ba[] = {0x02, 0x0b, 0x03, 0x00, -128, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x1a, 0x0e, 0x0a, 0x08, 0x08, 0x2e, 0, 0x10, 0x2b, 0, 0x18, 0x00, 0x10, 0x00, 0x18, 0x00}; + + int siz_arr = 0; + + clock_gettime(CLOCK_REALTIME, &tp); + + int idx = 1+6 + varint_encode_long(tp.tv_nsec, ba, 1+6); + + ba[idx++] = 0x1a; + int size1_idx = idx; + ba[idx++] = 0x0a; + + ba[idx++] = 0x0a; + int size2_idx = idx; + ba[idx ++] = 0x04; + + ba[idx ++] = 0x08; + siz_arr = varint_encode_int(x, ba, idx); + idx += siz_arr; + ba[size1_idx] += siz_arr; + ba[size2_idx] += siz_arr; + + ba[idx ++] = 0x10; + siz_arr = varint_encode_int(y, ba, idx); + idx += siz_arr; + ba[size1_idx] += siz_arr; + ba[size2_idx] += siz_arr; + + ba[idx++] = 0x18; + ba[idx++] = 0x00; + + ba[idx++] = 0x10; + ba[idx++] = 0x00; + + ba[idx++] = 0x18; + ba[idx++] = action; + + aa_cmd_send (idx, ba, 0, NULL); +} + class HuMainWindow: public QMainWindow { public: @@ -234,12 +349,34 @@ class HuMainWindow: public QMainWindow {}; ~ HuMainWindow(){}; + void mousePressEvent ( QMouseEvent * event ) + { + if(event->button() == Qt::LeftButton) { + printf("\n***\n"); + printf("PRESSED MOUSE BUTTON AT X:%d, Y:%d\n", event->x(), event->y()); + printf("***\n"); + aa_touch(ACTION_DOWN, event->x(), event->y()); + } + }; + void mouseReleaseEvent ( QMouseEvent * event ) { if(event->button() == Qt::LeftButton) { printf("\n***\n"); - printf("YOU CLICKED MOUSE AT X:%d, Y:%d\n", event->x(), event->y()); + printf("RELEASED MOUSE BUTTON AT X:%d, Y:%d\n", event->x(), event->y()); + printf("***\n"); + aa_touch(ACTION_UP, event->x(), event->y()); + } + }; + + void mouseMoveEvent ( QMouseEvent * event ) + { + /* Was left button held down when the move event occurred? */ + if(event->buttons() == Qt::LeftButton) { + printf("\n***\n"); + printf("MOVED MOUSE TO X:%d, Y:%d\n", event->x(), event->y()); printf("***\n"); + aa_touch(ACTION_MOVE, event->x(), event->y()); } }; }; From 4cf32fe82751ec69b7b8df0a3b7dff0a621f2d51 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Tue, 29 Sep 2015 15:01:49 -0400 Subject: [PATCH 11/14] moar main.cc cleanups Signed-off-by: Matt Porter --- gst/main.cc | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/gst/main.cc b/gst/main.cc index eb8fd75c..92074ca1 100644 --- a/gst/main.cc +++ b/gst/main.cc @@ -7,7 +7,6 @@ #include #include - #include "hu_uti.h" #include "hu_aap.h" @@ -38,7 +37,7 @@ static gboolean read_data(gst_app_t *app) } /* Is there a video buffer queued? */ - vbuf = read_head_buffer_get (& res_len); + vbuf = read_head_buffer_get (&res_len); if (vbuf != NULL) { printf("vbuf: %p res_len: %d\n", vbuf, res_len); @@ -54,14 +53,6 @@ static gboolean read_data(gst_app_t *app) g_debug("push buffer returned %d for %d bytes \n", ret, res_len); return FALSE; } - -#if 0 - if(size != BUFF_SIZE){ - ret = gst_app_src_end_of_stream(app->src); - g_debug("eos returned %d at %d\n", ret, __LINE__); - return FALSE; - } -#endif } return TRUE; From 7c19272c48af3f4bd517dd2f72b977e53937c4eb Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 30 Sep 2015 11:34:47 -0400 Subject: [PATCH 12/14] cleanup uleb128 encoding, prep for TS event cleanup Signed-off-by: Matt Porter --- gst/main.cc | 57 +++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/gst/main.cc b/gst/main.cc index 92074ca1..3d52aa86 100644 --- a/gst/main.cc +++ b/gst/main.cc @@ -250,39 +250,20 @@ static int aa_cmd_send(int cmd_len, unsigned char *cmd_buf, int res_max, unsigne return res_len; } -static int varint_encode_long (long val, unsigned char *ba, int idx) +static size_t uleb128_encode(uint64_t value, uint8_t *data) { - if (val >= 0x7fffffffffffffffL) { - printf("Too big"); - return 1; - } - long left = val; - for (int idx2 = 0; idx2 < 9; idx2 ++) { - ba[idx+idx2] = (char)(0x7f & left); - left = left >> 7; - if (left == 0) { - return idx2 + 1; - } - else if (idx2 < 9 - 1) { - ba [idx+idx2] |= 0x80; - } - } - return 9; -} - -static int varint_encode_int(int val, unsigned char *ba, int idx) -{ - if (val >= 1 << 14) { - printf("Too big"); - return 1; - } - ba [idx+0] = (char)(0x7f & (val >> 0)); - ba [idx+1] = (char)(0x7f & (val >> 7)); - if (ba [idx+1] != 0) { - ba [idx+0] |= 0x80; - return 2; - } - return 1; + uint8_t cbyte; + size_t enc_size = 0; + + do { + cbyte = value & 0x7f; + value >>= 7; + if (value != 0) + cbyte |= 0x80; + data[enc_size++] = cbyte; + } while (value != 0); + + return enc_size; } #define ACTION_DOWN 0 @@ -299,7 +280,7 @@ static void aa_touch (byte action, int x, int y) { clock_gettime(CLOCK_REALTIME, &tp); - int idx = 1+6 + varint_encode_long(tp.tv_nsec, ba, 1+6); + int idx = 1+6 + uleb128_encode(tp.tv_nsec, &ba[1+6]); ba[idx++] = 0x1a; int size1_idx = idx; @@ -310,19 +291,21 @@ static void aa_touch (byte action, int x, int y) { ba[idx ++] = 0x04; ba[idx ++] = 0x08; - siz_arr = varint_encode_int(x, ba, idx); + siz_arr = uleb128_encode(x, &ba[idx]); idx += siz_arr; ba[size1_idx] += siz_arr; ba[size2_idx] += siz_arr; ba[idx ++] = 0x10; - siz_arr = varint_encode_int(y, ba, idx); + siz_arr = uleb128_encode(y, &ba[idx]); idx += siz_arr; ba[size1_idx] += siz_arr; ba[size2_idx] += siz_arr; - ba[idx++] = 0x18; - ba[idx++] = 0x00; + /* So this is Z, it would be nice to handle it similarly and make a loop */ + ba[idx++] = 0x18; // Z axis flag + ba[idx++] = 0x00; // Z magnitude is zero and those sizes are already figuring on this fixed size of + // the Z coordinate array ba[idx++] = 0x10; ba[idx++] = 0x00; From d972fc7b1c31377f798214a5debdd01136db16ca Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 30 Sep 2015 16:30:11 -0400 Subject: [PATCH 13/14] second part of cleanup loop for axes, start cleanup using memcpy of preamble, sizes, postamble Signed-off-by: Matt Porter --- gst/main.cc | 79 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/gst/main.cc b/gst/main.cc index 3d52aa86..dce8fc35 100644 --- a/gst/main.cc +++ b/gst/main.cc @@ -269,51 +269,62 @@ static size_t uleb128_encode(uint64_t value, uint8_t *data) #define ACTION_DOWN 0 #define ACTION_UP 1 #define ACTION_MOVE 2 +#define TS_REQ_SIZE 32 +#define TS_DATA_OFFSET 7 +static const uint8_t ts_header[] ={0x02, 0x0b, 0x03, 0x00, 0x80, 0x01, 0x08}; +static const uint8_t ts_sizes[] = {0x1a, 0x09, 0x0a, 0x03}; static void aa_touch (byte action, int x, int y) { struct timespec tp; - - //0 1 - 9 10 X: 15, 16 Y: 18, 19 25 - unsigned char ba[] = {0x02, 0x0b, 0x03, 0x00, -128, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x1a, 0x0e, 0x0a, 0x08, 0x08, 0x2e, 0, 0x10, 0x2b, 0, 0x18, 0x00, 0x10, 0x00, 0x18, 0x00}; - + uint8_t *buf; + int idx; int siz_arr = 0; + int size1_idx, size2_idx, i; + int axis = 0; + int coordinates[3] = {x, y, 0}; + + buf = (uint8_t *)malloc(32); + if(!buf) { + printf("DOOMED!!!\n"); + return; + } clock_gettime(CLOCK_REALTIME, &tp); - int idx = 1+6 + uleb128_encode(tp.tv_nsec, &ba[1+6]); - - ba[idx++] = 0x1a; - int size1_idx = idx; - ba[idx++] = 0x0a; - - ba[idx++] = 0x0a; - int size2_idx = idx; - ba[idx ++] = 0x04; - - ba[idx ++] = 0x08; - siz_arr = uleb128_encode(x, &ba[idx]); - idx += siz_arr; - ba[size1_idx] += siz_arr; - ba[size2_idx] += siz_arr; - - ba[idx ++] = 0x10; - siz_arr = uleb128_encode(y, &ba[idx]); - idx += siz_arr; - ba[size1_idx] += siz_arr; - ba[size2_idx] += siz_arr; + memcpy(buf, ts_header, sizeof(ts_header)); + idx = sizeof(ts_header) + + uleb128_encode(tp.tv_nsec, buf + sizeof(ts_header)); + /* Location of size1/size2 fields can be calculated based on + * the above idx value + */ + buf[idx++] = 0x1a; /* Some kind of flag? */ + size1_idx = idx; + buf[idx++] = 0x09; /* size1 defaults to 0x0a, now 0x09 */ + buf[idx++] = 0x0a; /* Some kind of flag? */ + size2_idx = idx; + buf[idx++] = 0x03; /* size2 default to 0x04, now 0x03 */ + + /* Then loop to set three axes */ + for (i=0; i<3; i++) { + axis += 0x08; + buf[idx++] = axis; + siz_arr = uleb128_encode(coordinates[i], &buf[idx]); + idx += siz_arr; + buf[size1_idx] += siz_arr; + buf[size2_idx] += siz_arr; + } - /* So this is Z, it would be nice to handle it similarly and make a loop */ - ba[idx++] = 0x18; // Z axis flag - ba[idx++] = 0x00; // Z magnitude is zero and those sizes are already figuring on this fixed size of - // the Z coordinate array + /* This stuff could be copied in, postamble? */ + buf[idx++] = 0x10; + buf[idx++] = 0x00; + buf[idx++] = 0x18; - ba[idx++] = 0x10; - ba[idx++] = 0x00; + /* Then fill in action */ + buf[idx++] = action; - ba[idx++] = 0x18; - ba[idx++] = action; + aa_cmd_send (idx, buf, 0, NULL); - aa_cmd_send (idx, ba, 0, NULL); + free(buf); } class HuMainWindow: public QMainWindow From d793f4735df0efc58417083ef254b9ce97c3525b Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 30 Sep 2015 17:38:31 -0400 Subject: [PATCH 14/14] moar touch event cleanups..looks good enough now Signed-off-by: Matt Porter --- gst/main.cc | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/gst/main.cc b/gst/main.cc index dce8fc35..3fd80910 100644 --- a/gst/main.cc +++ b/gst/main.cc @@ -234,12 +234,14 @@ static int aa_cmd_send(int cmd_len, unsigned char *cmd_buf, int res_max, unsigne ret = hu_aap_enc_send (chan, cmd_buf+4, cmd_len - 4); if (ret < 0) { printf("aa_cmd_send(): hu_aap_enc_send() failed with (%d)\n", ret); + free(res_buf); return ret; } dq_buf = read_head_buffer_get(&res_len); if (!dq_buf || res_len <= 0) { printf("No data dq_buf!\n"); + free(res_buf); return 0; } memcpy(res_buf, dq_buf, res_len); @@ -269,12 +271,12 @@ static size_t uleb128_encode(uint64_t value, uint8_t *data) #define ACTION_DOWN 0 #define ACTION_UP 1 #define ACTION_MOVE 2 -#define TS_REQ_SIZE 32 -#define TS_DATA_OFFSET 7 +#define TS_MAX_REQ_SZ 32 static const uint8_t ts_header[] ={0x02, 0x0b, 0x03, 0x00, 0x80, 0x01, 0x08}; static const uint8_t ts_sizes[] = {0x1a, 0x09, 0x0a, 0x03}; +static const uint8_t ts_footer[] = {0x10, 0x00, 0x18}; -static void aa_touch (byte action, int x, int y) { +static void aa_touch_event(uint8_t action, int x, int y) { struct timespec tp; uint8_t *buf; int idx; @@ -283,45 +285,44 @@ static void aa_touch (byte action, int x, int y) { int axis = 0; int coordinates[3] = {x, y, 0}; - buf = (uint8_t *)malloc(32); + buf = (uint8_t *)malloc(TS_MAX_REQ_SZ); if(!buf) { - printf("DOOMED!!!\n"); + printf("Failed to allocate touchscreen event buffer\n"); return; } + /* Fetch the time stamp */ clock_gettime(CLOCK_REALTIME, &tp); + /* Copy header */ memcpy(buf, ts_header, sizeof(ts_header)); idx = sizeof(ts_header) + uleb128_encode(tp.tv_nsec, buf + sizeof(ts_header)); - /* Location of size1/size2 fields can be calculated based on - * the above idx value - */ - buf[idx++] = 0x1a; /* Some kind of flag? */ - size1_idx = idx; - buf[idx++] = 0x09; /* size1 defaults to 0x0a, now 0x09 */ - buf[idx++] = 0x0a; /* Some kind of flag? */ - size2_idx = idx; - buf[idx++] = 0x03; /* size2 default to 0x04, now 0x03 */ - - /* Then loop to set three axes */ + size1_idx = idx + 1; + size2_idx = idx + 3; + + /* Copy sizes */ + memcpy(buf+idx, ts_sizes, sizeof(ts_sizes)); + idx += sizeof(ts_sizes); + + /* Set magnitude of each axis */ for (i=0; i<3; i++) { axis += 0x08; buf[idx++] = axis; + /* FIXME The following can be optimzed to update size1/2 at end of loop */ siz_arr = uleb128_encode(coordinates[i], &buf[idx]); idx += siz_arr; buf[size1_idx] += siz_arr; buf[size2_idx] += siz_arr; } - /* This stuff could be copied in, postamble? */ - buf[idx++] = 0x10; - buf[idx++] = 0x00; - buf[idx++] = 0x18; + /* Copy footer */ + memcpy(buf+idx, ts_footer, sizeof(ts_footer)); + idx += sizeof(ts_footer); - /* Then fill in action */ buf[idx++] = action; + /* Send touch event */ aa_cmd_send (idx, buf, 0, NULL); free(buf); @@ -340,7 +341,7 @@ class HuMainWindow: public QMainWindow printf("\n***\n"); printf("PRESSED MOUSE BUTTON AT X:%d, Y:%d\n", event->x(), event->y()); printf("***\n"); - aa_touch(ACTION_DOWN, event->x(), event->y()); + aa_touch_event(ACTION_DOWN, event->x(), event->y()); } }; @@ -350,7 +351,7 @@ class HuMainWindow: public QMainWindow printf("\n***\n"); printf("RELEASED MOUSE BUTTON AT X:%d, Y:%d\n", event->x(), event->y()); printf("***\n"); - aa_touch(ACTION_UP, event->x(), event->y()); + aa_touch_event(ACTION_UP, event->x(), event->y()); } }; @@ -361,7 +362,7 @@ class HuMainWindow: public QMainWindow printf("\n***\n"); printf("MOVED MOUSE TO X:%d, Y:%d\n", event->x(), event->y()); printf("***\n"); - aa_touch(ACTION_MOVE, event->x(), event->y()); + aa_touch_event(ACTION_MOVE, event->x(), event->y()); } }; };