mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
UIBC support
Basic support for UIBC (single mouse events and key events) - Option --uibc on miracle-sinkctl to enable it - Option --log-journal-level to see player execution on journalctl - Controller for uibc miracle-uibcctl - Player based on PyGtk to receive and communicate mouse and keyevents closes #57
This commit is contained in:
parent
4637409d0b
commit
1e69dd6dae
21 changed files with 1258 additions and 79 deletions
|
@ -1,9 +1,10 @@
|
|||
set(CMAKE_C_FLAGS "-std=gnu11")
|
||||
set(CMAKE_C_FLAGS "-std=gnu11 ${CMAKE_C_FLAGS}")
|
||||
|
||||
add_subdirectory(shared)
|
||||
add_subdirectory(wifi)
|
||||
add_subdirectory(dhcp)
|
||||
add_subdirectory(ctl)
|
||||
add_subdirectory(uibc)
|
||||
|
||||
set(miracled_SRCS miracled.h miracled.c)
|
||||
add_executable(miracled ${miracled_SRCS})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
include $(top_srcdir)/common.am
|
||||
SUBDIRS = shared wifi dhcp ctl
|
||||
SUBDIRS = shared wifi dhcp ctl uibc
|
||||
|
||||
bin_PROGRAMS = miracled
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@ target_link_libraries(miracle-wifictl miracle-shared)
|
|||
|
||||
set(miracle-sinkctl_SRCS ctl.h
|
||||
ctl-cli.c
|
||||
ctl-sink.h
|
||||
ctl-sink.c
|
||||
ctl-wifi.c
|
||||
sinkctl.c
|
||||
wfd.c)
|
||||
|
||||
|
||||
add_executable(miracle-sinkctl ${miracle-sinkctl_SRCS})
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ miracle_wifictl_LDADD = \
|
|||
miracle_sinkctl_SOURCES = \
|
||||
ctl.h \
|
||||
ctl-cli.c \
|
||||
ctl-sink.h \
|
||||
ctl-sink.c \
|
||||
ctl-wifi.c \
|
||||
wfd.c \
|
||||
|
|
|
@ -17,52 +17,8 @@
|
|||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "ctl.h"
|
||||
#include "rtsp.h"
|
||||
#include "shl_macro.h"
|
||||
#include "shl_util.h"
|
||||
#include "wfd.h"
|
||||
#include "ctl-sink.h"
|
||||
|
||||
struct ctl_sink {
|
||||
sd_event *event;
|
||||
|
||||
char *target;
|
||||
char *session;
|
||||
char *url;
|
||||
char *uibc_setting;
|
||||
struct sockaddr_storage addr;
|
||||
size_t addr_size;
|
||||
int fd;
|
||||
sd_event_source *fd_source;
|
||||
|
||||
struct rtsp *rtsp;
|
||||
|
||||
bool connected : 1;
|
||||
bool hup : 1;
|
||||
|
||||
uint32_t resolutions_cea;
|
||||
uint32_t resolutions_vesa;
|
||||
uint32_t resolutions_hh;
|
||||
|
||||
int hres;
|
||||
int vres;
|
||||
};
|
||||
static const int DEFAULT_UIBC_PORT = 7239;
|
||||
static const int DEFAULT_RSTP_PORT = 1991;
|
||||
/*
|
||||
* RTSP Session
|
||||
*/
|
||||
|
@ -158,7 +114,7 @@ static void sink_handle_get_parameter(struct ctl_sink *s,
|
|||
if (rtsp_message_read(m, "{<>}", "wfd_client_rtp_ports") >= 0) {
|
||||
char wfd_client_rtp_ports[128];
|
||||
sprintf(wfd_client_rtp_ports,
|
||||
"wfd_client_rtp_ports: RTP/AVP/UDP;unicast %d 0 mode=play", DEFAULT_RSTP_PORT);
|
||||
"wfd_client_rtp_ports: RTP/AVP/UDP;unicast %d 0 mode=play", rstp_port);
|
||||
r = rtsp_message_append(rep, "{&}",
|
||||
wfd_client_rtp_ports);
|
||||
if (r < 0)
|
||||
|
@ -166,12 +122,12 @@ static void sink_handle_get_parameter(struct ctl_sink *s,
|
|||
}
|
||||
|
||||
/* wfd_uibc_capability */
|
||||
if (rtsp_message_read(m, "{<>}", "wfd_uibc_capability") >= 0) {
|
||||
if (rtsp_message_read(m, "{<>}", "wfd_uibc_capability") >= 0 && uibc) {
|
||||
char wfd_uibc_capability[512];
|
||||
sprintf(wfd_uibc_capability,
|
||||
"wfd_uibc_capability: input_category_list=GENERIC;"
|
||||
"generic_cap_list=Mouse,SingleTouch,Keyboard,Camera;"
|
||||
"hidc_cap_list=none;port=%d", DEFAULT_UIBC_PORT);
|
||||
"generic_cap_list=Mouse,SingleTouch;"
|
||||
"hidc_cap_list=none;port=none");
|
||||
r = rtsp_message_append(rep, "{&}", wfd_uibc_capability);
|
||||
if (r < 0)
|
||||
return cli_vERR(r);
|
||||
|
@ -243,7 +199,7 @@ static int sink_set_format(struct ctl_sink *s,
|
|||
if (hres && vres) {
|
||||
s->hres = hres;
|
||||
s->vres = vres;
|
||||
ctl_fn_sink_resolution_set(s, hres, vres);
|
||||
ctl_fn_sink_resolution_set(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +213,7 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
|||
_rtsp_message_unref_ struct rtsp_message *rep = NULL;
|
||||
const char *trigger;
|
||||
const char *url;
|
||||
const char *uibc_config;
|
||||
const char *uibc_setting;
|
||||
char *nu;
|
||||
unsigned int cea_res, vesa_res, hh_res;
|
||||
|
@ -290,6 +247,30 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
|||
}
|
||||
}
|
||||
|
||||
/* M4 (or any other) can pass presentation URLs */
|
||||
r = rtsp_message_read(m, "{<s>}", "wfd_uibc_capability", &uibc_config);
|
||||
if (r >= 0) {
|
||||
if (!s->uibc_config || strcmp(s->uibc_config, uibc_config)) {
|
||||
nu = strdup(uibc_config);
|
||||
if (!nu)
|
||||
return cli_vENOMEM();
|
||||
|
||||
free(s->uibc_config);
|
||||
s->uibc_config = nu;
|
||||
|
||||
char* token = strtok(uibc_config, ";");
|
||||
|
||||
while (token) {
|
||||
if (sscanf(token, "port=%d", &uibc_port)) {
|
||||
break;
|
||||
}
|
||||
token = strtok(0, ";");
|
||||
}
|
||||
|
||||
cli_debug("Got URL: %s\n", s->url);
|
||||
}
|
||||
}
|
||||
|
||||
/* M4 (or any other) can pass presentation URLs */
|
||||
r = rtsp_message_read(m, "{<s>}", "wfd_uibc_setting", &uibc_setting);
|
||||
if (r >= 0) {
|
||||
|
@ -330,9 +311,9 @@ static void sink_handle_set_parameter(struct ctl_sink *s,
|
|||
if (r < 0)
|
||||
return cli_vERR(r);
|
||||
|
||||
r = rtsp_message_append(rep, "<s>",
|
||||
"Transport",
|
||||
"RTP/AVP/UDP;unicast;client_port=1991");
|
||||
char rtsp_setup[128];
|
||||
sprintf(rtsp_setup, "RTP/AVP/UDP;unicast;client_port=%d", rstp_port);
|
||||
r = rtsp_message_append(rep, "<s>", "Transport", rtsp_setup);
|
||||
if (r < 0)
|
||||
return cli_vERR(r);
|
||||
|
||||
|
|
72
src/ctl/ctl-sink.h
Normal file
72
src/ctl/ctl-sink.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||
*
|
||||
* MiracleCast is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MiracleCast is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CTL_SINK_H
|
||||
#define CTL_SINK_H
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <systemd/sd-event.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "ctl.h"
|
||||
|
||||
#include "rtsp.h"
|
||||
#include "shl_macro.h"
|
||||
#include "shl_util.h"
|
||||
#include "wfd.h"
|
||||
|
||||
extern int rstp_port;
|
||||
extern bool uibc;
|
||||
extern int uibc_port;
|
||||
|
||||
struct ctl_sink {
|
||||
sd_event *event;
|
||||
|
||||
char *target;
|
||||
char *session;
|
||||
char *url;
|
||||
char *uibc_config;
|
||||
char *uibc_setting;
|
||||
struct sockaddr_storage addr;
|
||||
size_t addr_size;
|
||||
int fd;
|
||||
sd_event_source *fd_source;
|
||||
|
||||
struct rtsp *rtsp;
|
||||
|
||||
bool connected : 1;
|
||||
bool hup : 1;
|
||||
|
||||
uint32_t resolutions_cea;
|
||||
uint32_t resolutions_vesa;
|
||||
uint32_t resolutions_hh;
|
||||
|
||||
int hres;
|
||||
int vres;
|
||||
};
|
||||
|
||||
#endif /* CTL_SINK_H */
|
|
@ -241,7 +241,7 @@ void ctl_fn_link_free(struct ctl_link *l);
|
|||
|
||||
void ctl_fn_sink_connected(struct ctl_sink *s);
|
||||
void ctl_fn_sink_disconnected(struct ctl_sink *s);
|
||||
void ctl_fn_sink_resolution_set(struct ctl_sink *s, int hres, int vres);
|
||||
void ctl_fn_sink_resolution_set(struct ctl_sink *s);
|
||||
|
||||
void cli_fn_help(void);
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "ctl.h"
|
||||
#include "ctl-sink.h"
|
||||
#include "wfd.h"
|
||||
#include "shl_macro.h"
|
||||
#include "shl_util.h"
|
||||
|
@ -53,8 +54,15 @@ static struct ctl_link *running_link;
|
|||
static struct ctl_peer *running_peer;
|
||||
static struct ctl_peer *pending_peer;
|
||||
|
||||
void launch_player(struct ctl_sink *s);
|
||||
|
||||
char *gst_scale_res;
|
||||
int gst_audio_en = 1;
|
||||
static const int DEFAULT_RSTP_PORT = 1991;
|
||||
bool uibc;
|
||||
int rstp_port;
|
||||
int uibc_port;
|
||||
|
||||
unsigned int wfd_supported_res_cea = 0x0000001f; /* up to 720x576 */
|
||||
unsigned int wfd_supported_res_vesa = 0x00000003; /* up to 800x600 */
|
||||
unsigned int wfd_supported_res_hh = 0x00000000; /* not supported */
|
||||
|
@ -335,12 +343,10 @@ static const struct cli_cmd cli_cmds[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
static void spawn_gst(int hres, int vres)
|
||||
static void spawn_gst(struct ctl_sink *s)
|
||||
{
|
||||
char *argv[64];
|
||||
char resolution[64];
|
||||
pid_t pid;
|
||||
int fd_journal, i;
|
||||
int fd_journal;
|
||||
sigset_t mask;
|
||||
|
||||
if (sink_pid > 0)
|
||||
|
@ -357,7 +363,7 @@ static void spawn_gst(int hres, int vres)
|
|||
|
||||
/* redirect stdout/stderr to journal */
|
||||
fd_journal = sd_journal_stream_fd("miracle-sinkctl-gst",
|
||||
LOG_INFO,
|
||||
LOG_DEBUG,
|
||||
false);
|
||||
if (fd_journal >= 0) {
|
||||
/* dup journal-fd to stdout and stderr */
|
||||
|
@ -368,8 +374,34 @@ static void spawn_gst(int hres, int vres)
|
|||
dup2(2, 1);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
argv[i++] = (char*) "/miracle-gst.sh";
|
||||
launch_player(s);
|
||||
_exit(1);
|
||||
} else {
|
||||
sink_pid = pid;
|
||||
}
|
||||
}
|
||||
|
||||
void launch_player(struct ctl_sink *s) {
|
||||
char *argv[64];
|
||||
char resolution[64];
|
||||
char port[64];
|
||||
char uibc_portStr[64];
|
||||
int i = 0;
|
||||
char* player;
|
||||
if (uibc) {
|
||||
// player = "gstplayer";
|
||||
player = "uibc-viewer";
|
||||
} else {
|
||||
player = "miracle-gst";
|
||||
}
|
||||
|
||||
argv[i++] = player;
|
||||
if (uibc) {
|
||||
argv[i++] = s->target;
|
||||
sprintf(uibc_portStr, "%d", uibc_port);
|
||||
argv[i++] = uibc_portStr;
|
||||
// argv[i++] = "--daemon";
|
||||
}
|
||||
if (cli_max_sev >= 7)
|
||||
argv[i++] = "-d 3";
|
||||
if (gst_audio_en)
|
||||
|
@ -378,18 +410,55 @@ static void spawn_gst(int hres, int vres)
|
|||
argv[i++] = "-s";
|
||||
argv[i++] = gst_scale_res;
|
||||
}
|
||||
if (hres && vres) {
|
||||
sprintf(resolution, "%dx%d", hres, vres);
|
||||
argv[i++] = "-p";
|
||||
sprintf(port, "%d", rstp_port);
|
||||
argv[i++] = port;
|
||||
|
||||
if (s->hres && s->vres) {
|
||||
sprintf(resolution, "%dx%d", s->hres, s->vres);
|
||||
argv[i++] = "-r";
|
||||
argv[i++] = resolution;
|
||||
}
|
||||
|
||||
argv[i] = NULL;
|
||||
|
||||
execve(argv[0], argv, environ);
|
||||
_exit(1);
|
||||
} else {
|
||||
sink_pid = pid;
|
||||
i = 0;
|
||||
int size = 0;
|
||||
while (argv[i]) {
|
||||
size += strlen(argv[i++] + 1);
|
||||
}
|
||||
|
||||
char* player_command = malloc(size);
|
||||
i = 0;
|
||||
strcpy(player_command, argv[i++]);
|
||||
while (argv[i]) {
|
||||
strcat(player_command, " ");
|
||||
strcat(player_command, argv[i++]);
|
||||
}
|
||||
log_debug("player command: %s", player_command);
|
||||
//free(player_command);
|
||||
if (execvpe(argv[0], argv, environ) < 0) {
|
||||
cli_debug("stream player failed (%d): %m", errno);
|
||||
int i = 0;
|
||||
cli_debug("printing environment: ");
|
||||
while (environ[i]) {
|
||||
cli_debug("%s", environ[i++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void launch_uibc_daemon(int port) {
|
||||
char *argv[64];
|
||||
char portStr[64];
|
||||
int i = 0;
|
||||
argv[i++] = "miracle-uibcctl";
|
||||
argv[i++] = "localhost";
|
||||
sprintf(portStr, "%d", port);
|
||||
argv[i++] = portStr;
|
||||
argv[i] = NULL;
|
||||
|
||||
cli_debug("uibc daemon: %s", argv[0]);
|
||||
execvpe(argv[0], argv, environ);
|
||||
}
|
||||
|
||||
static void kill_gst(void)
|
||||
|
@ -418,11 +487,11 @@ void ctl_fn_sink_disconnected(struct ctl_sink *s)
|
|||
}
|
||||
}
|
||||
|
||||
void ctl_fn_sink_resolution_set(struct ctl_sink *s, int hres, int vres)
|
||||
void ctl_fn_sink_resolution_set(struct ctl_sink *s)
|
||||
{
|
||||
cli_printf("SINK set resolution %dx%d\n", hres, vres);
|
||||
cli_printf("SINK set resolution %dx%d\n", s->hres, s->vres);
|
||||
if (sink_connected)
|
||||
spawn_gst(hres, vres);
|
||||
spawn_gst(s);
|
||||
}
|
||||
|
||||
void ctl_fn_peer_new(struct ctl_peer *p)
|
||||
|
@ -604,14 +673,17 @@ void cli_fn_help()
|
|||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --log-level <lvl> Maximum level for log messages\n"
|
||||
" --log-journal-level <lvl> Maximum level for journal log messages\n"
|
||||
" --audio <0/1> Enable audio support (default %d)\n"
|
||||
" --scale WxH Scale to resolution\n"
|
||||
" --port <port> Port for rtsp (default %d)\n"
|
||||
" --uibc Enables UIBC\n"
|
||||
" --res <n,n,n> Supported resolutions masks (CEA, VESA, HH)\n"
|
||||
" default CEA %08X\n"
|
||||
" default VESA %08X\n"
|
||||
" default HH %08X\n"
|
||||
"\n"
|
||||
, program_invocation_short_name, gst_audio_en,
|
||||
, program_invocation_short_name, gst_audio_en, DEFAULT_RSTP_PORT,
|
||||
wfd_supported_res_cea, wfd_supported_res_vesa, wfd_supported_res_hh
|
||||
);
|
||||
wfd_print_resolutions();
|
||||
|
@ -680,21 +752,30 @@ static int parse_argv(int argc, char *argv[])
|
|||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_LOG_LEVEL,
|
||||
ARG_JOURNAL_LEVEL,
|
||||
ARG_AUDIO,
|
||||
ARG_SCALE,
|
||||
ARG_RES,
|
||||
ARG_PORT,
|
||||
ARG_UIBC,
|
||||
};
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
|
||||
{ "log-journal-level", required_argument, NULL, ARG_JOURNAL_LEVEL },
|
||||
{ "audio", required_argument, NULL, ARG_AUDIO },
|
||||
{ "scale", required_argument, NULL, ARG_SCALE },
|
||||
{ "res", required_argument, NULL, ARG_RES },
|
||||
{ "port", required_argument, NULL, ARG_PORT },
|
||||
{ "uibc", no_argument, NULL, ARG_UIBC },
|
||||
{}
|
||||
};
|
||||
int c;
|
||||
|
||||
uibc = false;
|
||||
rstp_port = DEFAULT_RSTP_PORT;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
|
@ -705,6 +786,9 @@ static int parse_argv(int argc, char *argv[])
|
|||
case ARG_LOG_LEVEL:
|
||||
cli_max_sev = log_parse_arg(optarg);
|
||||
break;
|
||||
case ARG_JOURNAL_LEVEL:
|
||||
log_max_sev = log_parse_arg(optarg);
|
||||
break;
|
||||
case ARG_AUDIO:
|
||||
gst_audio_en = atoi(optarg);
|
||||
break;
|
||||
|
@ -717,6 +801,12 @@ static int parse_argv(int argc, char *argv[])
|
|||
&wfd_supported_res_vesa,
|
||||
&wfd_supported_res_hh);
|
||||
break;
|
||||
case ARG_PORT:
|
||||
rstp_port = atoi(optarg);
|
||||
break;
|
||||
case ARG_UIBC:
|
||||
uibc = true;
|
||||
break;
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
10
src/uibc/CMakeLists.txt
Normal file
10
src/uibc/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
set(miracle-uibcctl_SRCS miracle-uibcctl.h
|
||||
miracle-uibcctl.c)
|
||||
|
||||
add_executable(miracle-uibcctl ${miracle-uibcctl_SRCS})
|
||||
target_link_libraries(miracle-uibcctl PRIVATE miracle-shared)
|
||||
target_link_libraries(miracle-uibcctl PUBLIC m)
|
||||
|
||||
install(TARGETS miracle-uibcctl DESTINATION bin)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/shared)
|
16
src/uibc/Makefile.am
Normal file
16
src/uibc/Makefile.am
Normal file
|
@ -0,0 +1,16 @@
|
|||
include $(top_srcdir)/common.am
|
||||
|
||||
bin_PROGRAMS = miracle-uibcctl
|
||||
|
||||
miracle_uibcctl_SOURCES = \
|
||||
miracle-uibcctl.h \
|
||||
miracle-uibcctl.c
|
||||
|
||||
miracle_uibctcl_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(DEPS_CFLAGS)
|
||||
|
||||
miracle_uibcctl_LDADD = \
|
||||
../shared/libmiracle-shared.la \
|
||||
$(LIBM)
|
||||
|
624
src/uibc/miracle-uibcctl.c
Normal file
624
src/uibc/miracle-uibcctl.c
Normal file
|
@ -0,0 +1,624 @@
|
|||
|
||||
#include "miracle-uibcctl.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
//TODO: Add miracle TUI interface
|
||||
//TODO: Add parsearg
|
||||
//--daemon (read stdin)
|
||||
|
||||
int portno;
|
||||
struct hostent *server;
|
||||
int sockfd;
|
||||
struct sockaddr_in serv_addr;
|
||||
char buffer[256];
|
||||
int r;
|
||||
|
||||
log_max_sev = LOG_INFO;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr, " %s <hostname> <port>\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
server = gethostbyname(argv[1]);
|
||||
portno = atoi(argv[2]);
|
||||
|
||||
log_info("server %s port %d", argv[1], portno);
|
||||
|
||||
if (server == NULL) {
|
||||
fprintf(stderr,"ERROR, no such host\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (sockfd < 0) {
|
||||
perror("ERROR opening socket");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
bcopy(server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
|
||||
serv_addr.sin_port = htons(portno);
|
||||
|
||||
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
|
||||
perror("ERROR connecting");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
bool daemon = true;
|
||||
while(1) {
|
||||
if (!daemon) {
|
||||
printf("enter event <type>,<count>,<id>,<x>,<y>: ");
|
||||
}
|
||||
bzero(buffer, 256);
|
||||
fgets(buffer, 255, stdin);
|
||||
if (buffer == NULL) {
|
||||
break;
|
||||
}
|
||||
if (daemon) {
|
||||
printf("input: %s", buffer);
|
||||
}
|
||||
char type = buffer[0];
|
||||
UibcMessage uibcmessage;
|
||||
if (type == '0' || type == '1') {
|
||||
uibcmessage = buildUibcMessage(GENERIC_TOUCH_DOWN, buffer, 1, 1);
|
||||
} else if (type == '3' || type == '4') {
|
||||
uibcmessage = buildUibcMessage(GENERIC_KEY_DOWN, buffer, 1, 1);
|
||||
} else {
|
||||
printf("unknow event type: %s", buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = sendUibcMessage(&uibcmessage, sockfd);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
const char *int2binary(int x, int padding)
|
||||
{
|
||||
char *b;
|
||||
int min_padding = x > 0 ? floor(log2(x)) : 0;
|
||||
if (padding < min_padding)
|
||||
{
|
||||
padding = min_padding;
|
||||
}
|
||||
|
||||
b = (char *)malloc (sizeof (char *) * padding + 1);
|
||||
strcpy(b, "");
|
||||
|
||||
int z;
|
||||
for (z = pow(2,padding); z > 0; z >>= 1)
|
||||
{
|
||||
strcat(b, ((x & z) == z) ? "1" : "0");
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
int sendUibcMessage(UibcMessage* uibcmessage, int sockfd) {
|
||||
ssize_t n;
|
||||
|
||||
printf("sending %d bytes\n", uibcmessage->m_PacketDataLen);
|
||||
|
||||
n = write(sockfd, uibcmessage->m_PacketData , uibcmessage->m_PacketDataLen);
|
||||
|
||||
if (n < 0) {
|
||||
perror("ERROR writing to socket");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
UibcMessage buildUibcMessage(MessageType type,
|
||||
const char* inEventDesc,
|
||||
double widthRatio,
|
||||
double heightRatio) {
|
||||
UibcMessage uibcmessage;
|
||||
uibcmessage.m_PacketData = NULL;
|
||||
uibcmessage.m_PacketDataLen = 0;
|
||||
uibcmessage.m_DataValid = false;
|
||||
|
||||
switch (type) {
|
||||
case GENERIC_TOUCH_DOWN:
|
||||
case GENERIC_TOUCH_UP:
|
||||
case GENERIC_TOUCH_MOVE:
|
||||
getUIBCGenericTouchPacket(inEventDesc,
|
||||
&uibcmessage,
|
||||
widthRatio,
|
||||
heightRatio);
|
||||
break;
|
||||
|
||||
case GENERIC_KEY_DOWN:
|
||||
case GENERIC_KEY_UP:
|
||||
getUIBCGenericKeyPacket(inEventDesc, &uibcmessage);
|
||||
break;
|
||||
|
||||
case GENERIC_ZOOM:
|
||||
getUIBCGenericZoomPacket(inEventDesc, &uibcmessage);
|
||||
break;
|
||||
|
||||
case GENERIC_VERTICAL_SCROLL:
|
||||
case GENERIC_HORIZONTAL_SCROLL:
|
||||
getUIBCGenericScalePacket(inEventDesc, &uibcmessage);
|
||||
break;
|
||||
|
||||
case GENERIC_ROTATE:
|
||||
getUIBCGenericRotatePacket(inEventDesc, &uibcmessage);
|
||||
break;
|
||||
};
|
||||
return uibcmessage;
|
||||
}
|
||||
|
||||
|
||||
// format: "typeId, number of pointers, pointer Id1, X coordnate, Y coordinate, pointer Id2, X coordnate, Y coordnate,..."
|
||||
void getUIBCGenericTouchPacket(const char *inEventDesc,
|
||||
UibcMessage* uibcmessage,
|
||||
double widthRatio,
|
||||
double heightRatio) {
|
||||
log_info("getUIBCGenericTouchPacket (%s)", inEventDesc);
|
||||
char* outData;
|
||||
int32_t typeId = 0;
|
||||
int32_t numberOfPointers = 0;
|
||||
size_t uibcBodyLen = 0;
|
||||
int32_t genericPacketLen = 0;
|
||||
int32_t temp;
|
||||
size_t size;
|
||||
|
||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
||||
|
||||
if ((int)size - 5 < 0 || ((int)size - 5) % 3 != 0) {
|
||||
log_error("getUIBCGenericTouchPacket (%s)", "bad input event");
|
||||
return;
|
||||
}
|
||||
int offset_split = 0;
|
||||
typeId = atoi(*(splitedStr + offset_split++));
|
||||
numberOfPointers = atoi(*(splitedStr + offset_split++));
|
||||
|
||||
genericPacketLen = numberOfPointers * 5 + 1;
|
||||
uibcBodyLen = genericPacketLen + 7; // Generic header length = 7
|
||||
//Padding to even number
|
||||
uibcBodyLen = (uibcBodyLen % 2 == 0) ? uibcBodyLen : (uibcBodyLen + 1);
|
||||
|
||||
outData = (char*)malloc(uibcBodyLen);
|
||||
// UIBC header Octets
|
||||
int offset_header = 0;
|
||||
//Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[offset_header++] = 0x00; // 000 0 0000
|
||||
outData[offset_header++] = 0x00; // 0000 0000
|
||||
|
||||
//Length(16 bits)
|
||||
outData[offset_header++] = (uibcBodyLen >> 8) & 0xFF; // first 8 bytes
|
||||
outData[offset_header++] = uibcBodyLen & 0xFF; // last 8 bytes
|
||||
|
||||
//Generic Input Body Format
|
||||
outData[offset_header++] = typeId & 0xFF; // Tyoe ID, 1 octet
|
||||
|
||||
// Length, 2 octets
|
||||
outData[offset_header++] = (genericPacketLen >> 8) & 0xFF; // first 8 bytes
|
||||
outData[offset_header++] = genericPacketLen & 0xFF; //last 8 bytes
|
||||
|
||||
// Number of pointers, 1 octet
|
||||
outData[offset_header++] = numberOfPointers & 0xFF;
|
||||
|
||||
int offset = 0;
|
||||
log_info("getUIBCGenericTouchPacket numberOfPointers=[%d]\n", numberOfPointers);
|
||||
for (int i = 0; i < numberOfPointers; i++) {
|
||||
int splitoffset = offset_split + (i * 3);
|
||||
temp = atoi(*(splitedStr + splitoffset++));
|
||||
offset = offset_header + ( i * 5);
|
||||
outData[offset++] = temp & 0xFF;
|
||||
log_info("getUIBCGenericTouchPacket PointerId=[%d]\n", temp);
|
||||
|
||||
temp = atoi(*(splitedStr + splitoffset++));
|
||||
temp = (int32_t)((double)temp / widthRatio);
|
||||
log_info("getUIBCGenericTouchPacket X-coordinate=[%d]\n", temp);
|
||||
outData[offset++] = (temp >> 8) & 0xFF;
|
||||
outData[offset++] = temp & 0xFF;
|
||||
|
||||
temp = atoi(*(splitedStr + splitoffset++));
|
||||
temp = (int32_t)((double)temp / heightRatio);
|
||||
log_info("getUIBCGenericTouchPacket Y-coordinate=[%d]\n", temp);
|
||||
outData[offset++] = (temp >> 8) & 0xFF;
|
||||
outData[offset++] = temp & 0xFF;
|
||||
}
|
||||
|
||||
while (offset <= uibcBodyLen) {
|
||||
outData[offset++] = 0x00;
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
free(*(splitedStr + i));
|
||||
}
|
||||
free(splitedStr);
|
||||
|
||||
binarydump(outData, uibcBodyLen);
|
||||
uibcmessage->m_DataValid = true;
|
||||
uibcmessage->m_PacketData = outData;
|
||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
||||
}
|
||||
|
||||
void hexdump(void *_data, size_t len)
|
||||
{
|
||||
unsigned char *data = _data;
|
||||
int count;
|
||||
|
||||
int line = 15;
|
||||
for (count = 0; count < len; count++) {
|
||||
if ((count & line) == 0) {
|
||||
fprintf(stderr,"%04zu: ", count);
|
||||
}
|
||||
fprintf(stderr,"%02x ", *data);
|
||||
data++;
|
||||
if ((count & line) == line) {
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
if ((count & line) != 0) {
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
void binarydump(void *_data, size_t len)
|
||||
{
|
||||
unsigned char *data = _data;
|
||||
int count;
|
||||
|
||||
int line = 7;
|
||||
for (count = 0; count < len; count++) {
|
||||
if ((count & line) == 0) {
|
||||
fprintf(stderr,"%04zu: ", count);
|
||||
}
|
||||
fprintf(stderr,"%s ", int2binary(*data, 8));
|
||||
data++;
|
||||
if ((count & line) == line) {
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
if ((count & line) != 0) {
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
// format: "typeId, Key code 1(0x00), Key code 2(0x00)"
|
||||
void getUIBCGenericKeyPacket(const char *inEventDesc,
|
||||
UibcMessage* uibcmessage) {
|
||||
log_info("getUIBCGenericKeyPacket (%s)", inEventDesc);
|
||||
char* outData = uibcmessage->m_PacketData;
|
||||
int32_t typeId = 0;
|
||||
int32_t uibcBodyLen = 0;
|
||||
int32_t genericPacketLen = 0;
|
||||
int32_t temp = 0;
|
||||
size_t size;
|
||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
||||
|
||||
if (size > 0) {
|
||||
|
||||
if (((int)size) % 3 != 0) {
|
||||
log_error("getUIBCGenericKeyPacket (%s)", "bad input event");
|
||||
return;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
log_info("getUIBCGenericKeyPacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
||||
|
||||
switch (i) {
|
||||
case 0: {
|
||||
typeId = atoi(*(splitedStr + i));
|
||||
log_info("getUIBCGenericKeyPacket typeId=[%d]\n", typeId);
|
||||
genericPacketLen = 5;
|
||||
uibcBodyLen = genericPacketLen + 7; // Generic header legth = 7
|
||||
outData = (char*)malloc(uibcBodyLen + 1);
|
||||
// UIBC header
|
||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
||||
//Generic Input Body Format
|
||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
||||
outData[7] = 0x00; // reserved
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
sscanf(*(splitedStr + i), " 0x%04X", &temp);
|
||||
if (temp == 0) {
|
||||
outData[8] = 0x00;
|
||||
outData[9] = 0x00;
|
||||
}
|
||||
log_info("getUIBCGenericKeyPacket key code 1=[%d]\n", temp);
|
||||
outData[8] = (temp >> 8) & 0xFF;
|
||||
outData[9] = temp & 0xFF;
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
sscanf(*(splitedStr + i), " 0x%04X", &temp);
|
||||
if (temp == 0) {
|
||||
outData[10] = 0x00;
|
||||
outData[11] = 0x00;
|
||||
}
|
||||
log_info("getUIBCGenericKeyPacket key code 2=[%d]\n", temp);
|
||||
outData[10] = (temp >> 8) & 0xFF;
|
||||
outData[11] = temp & 0xFF;
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
}
|
||||
break;
|
||||
}
|
||||
free(*(splitedStr + i));
|
||||
}
|
||||
}
|
||||
free(splitedStr);
|
||||
|
||||
binarydump(outData, uibcBodyLen);
|
||||
uibcmessage->m_DataValid = true;
|
||||
uibcmessage->m_PacketData = outData;
|
||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
||||
}
|
||||
|
||||
// format: "typeId, X coordnate, Y coordnate, integer part, fraction part"
|
||||
void getUIBCGenericZoomPacket(const char *inEventDesc, UibcMessage* uibcmessage) {
|
||||
log_info("getUIBCGenericZoomPacket (%s)", inEventDesc);
|
||||
char* outData = uibcmessage->m_PacketData;
|
||||
int32_t typeId;
|
||||
int32_t uibcBodyLen, genericPacketLen;
|
||||
int32_t xCoord, yCoord, integerPart, FractionPart;
|
||||
size_t size;
|
||||
|
||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
||||
|
||||
if (splitedStr) {
|
||||
int i;
|
||||
for (i = 0; * (splitedStr + i); i++) {
|
||||
//log_info("getUIBCGenericZoomPacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
||||
|
||||
switch (i) {
|
||||
case 0: {
|
||||
typeId = atoi(*(splitedStr + i));
|
||||
//log_info("getUIBCGenericZoomPacket typeId=[%d]\n", typeId);
|
||||
|
||||
genericPacketLen = 6;
|
||||
uibcBodyLen = genericPacketLen + 7; // Generic herder leh = 7
|
||||
outData = (char*)malloc(uibcBodyLen + 1);
|
||||
// UIBC header
|
||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
||||
//Generic Input Body Format
|
||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
xCoord = atoi(*(splitedStr + i));
|
||||
outData[7] = (xCoord >> 8) & 0xFF;
|
||||
outData[8] = xCoord & 0xFF;
|
||||
log_info("getUIBCGenericZoomPacket xCoord=[%d]\n", xCoord);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
yCoord = atoi(*(splitedStr + i));
|
||||
log_info("getUIBCGenericZoomPacket yCoord=[%d]\n", yCoord);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
integerPart = atoi(*(splitedStr + i));
|
||||
outData[11] = integerPart & 0xFF;
|
||||
//log_info("getUIBCGenericZoomPacket integerPart=[%d]\n", integerPart);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
FractionPart = atoi(*(splitedStr + i));
|
||||
outData[12] = FractionPart & 0xFF;
|
||||
//log_info("getUIBCGenericZoomPacket FractionPart=[%d]\n", FractionPart);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(*(splitedStr + i));
|
||||
}
|
||||
free(splitedStr);
|
||||
}
|
||||
//hexdump(outData, uibcBodyLen);
|
||||
uibcmessage->m_DataValid = true;
|
||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
||||
}
|
||||
|
||||
// format: "typeId, unit, direction, amount to scroll"
|
||||
void getUIBCGenericScalePacket(const char *inEventDesc, UibcMessage* uibcmessage) {
|
||||
log_info("getUIBCGenericScalePacket (%s)", inEventDesc);
|
||||
char* outData = uibcmessage->m_PacketData;
|
||||
int32_t typeId;
|
||||
int32_t uibcBodyLen, genericPacketLen;
|
||||
int32_t temp;
|
||||
size_t size;
|
||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
||||
|
||||
if (splitedStr) {
|
||||
int i;
|
||||
for (i = 0; * (splitedStr + i); i++) {
|
||||
//log_info("getUIBCGenericScalePacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
||||
|
||||
switch (i) {
|
||||
case 0: {
|
||||
typeId = atoi(*(splitedStr + i));
|
||||
//log_info("getUIBCGenericScalePacket typeId=[%d]\n", typeId);
|
||||
genericPacketLen = 2;
|
||||
uibcBodyLen = genericPacketLen + 7; // Generic herder leh = 7
|
||||
outData = (char*)malloc(uibcBodyLen + 1);
|
||||
// UIBC header
|
||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
||||
//Generic Input Body Format
|
||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
||||
outData[7] = 0x00; // Clear the byte
|
||||
outData[8] = 0x00; // Clear the byte
|
||||
/*
|
||||
B15B14; Scroll Unit Indication bits.
|
||||
0b00; the unit is a pixel (normalized with respect to the WFD Source display resolution that is conveyed in an RTSP M4 request message).
|
||||
0b01; the unit is a mouse notch (where the application is responsible for representing the number of pixels per notch).
|
||||
0b10-0b11; Reserved.
|
||||
|
||||
B13; Scroll Direction Indication bit.
|
||||
0b0; Scrolling to the right. Scrolling to the right means the displayed content being shifted to the left from a user perspective.
|
||||
0b1; Scrolling to the left. Scrolling to the left means the displayed content being shifted to the right from a user perspective.
|
||||
|
||||
B12:B0; Number of Scroll bits.
|
||||
Number of units for a Horizontal scroll.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
temp = atoi(*(splitedStr + i));
|
||||
//log_info("getUIBCGenericScalePacket unit=[%d]\n", temp);
|
||||
outData[7] = (temp >> 8) & 0xFF;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
temp = atoi(*(splitedStr + i));
|
||||
//log_info("getUIBCGenericScalePacket direction=[%d]\n", temp);
|
||||
outData[7] |= ((temp >> 10) & 0xFF);
|
||||
break;
|
||||
|
||||
}
|
||||
case 3: {
|
||||
temp = atoi(*(splitedStr + i));
|
||||
//log_info("getUIBCGenericScalePacket amount to scroll=[%d]\n", temp);
|
||||
outData[7] |= ((temp >> 12) & 0xFF);
|
||||
outData[8] = temp & 0xFF;
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(*(splitedStr + i));
|
||||
}
|
||||
|
||||
free(splitedStr);
|
||||
}
|
||||
//hexdump(outData, uibcBodyLen);
|
||||
uibcmessage->m_DataValid = true;
|
||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
||||
}
|
||||
|
||||
// format: "typeId, integer part, fraction part"
|
||||
void getUIBCGenericRotatePacket(const char * inEventDesc, UibcMessage* uibcmessage) {
|
||||
log_info("getUIBCGenericRotatePacket (%s)", inEventDesc);
|
||||
char* outData = uibcmessage->m_PacketData;
|
||||
int32_t typeId;
|
||||
int32_t uibcBodyLen, genericPacketLen;
|
||||
int32_t integerPart, FractionPart;
|
||||
size_t size;
|
||||
|
||||
char** splitedStr = str_split((char*)inEventDesc, ",", &size);
|
||||
|
||||
if (splitedStr) {
|
||||
int i;
|
||||
for (i = 0; * (splitedStr + i); i++) {
|
||||
//log_info("getUIBCGenericRotatePacket splitedStr tokens=[%s]\n", *(splitedStr + i));
|
||||
|
||||
switch (i) {
|
||||
case 0: {
|
||||
typeId = atoi(*(splitedStr + i));
|
||||
//log_info("getUIBCGenericRotatePacket typeId=[%d]\n", typeId);
|
||||
genericPacketLen = 2;
|
||||
uibcBodyLen = genericPacketLen + 7; // Generic herder leh = 7
|
||||
outData = (char*)malloc(uibcBodyLen + 1);
|
||||
// UIBC header
|
||||
outData[0] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[1] = 0x00; //Version (3 bits),T (1 bit),Reserved(8 bits),Input Category (4 bits)
|
||||
outData[2] = (uibcBodyLen >> 8) & 0xFF; //Length(16 bits)
|
||||
outData[3] = uibcBodyLen & 0xFF; //Length(16 bits)
|
||||
//Generic Input Body Format
|
||||
outData[4] = typeId & 0xFF; // Tyoe ID, 1 octet
|
||||
outData[5] = (genericPacketLen >> 8) & 0xFF; // Length, 2 octets
|
||||
outData[6] = genericPacketLen & 0xFF; // Length, 2 octets
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
integerPart = atoi(*(splitedStr + i));
|
||||
outData[7] = integerPart & 0xFF;
|
||||
//log_info("getUIBCGenericRotatePacket integerPart=[%d]\n", integerPart);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
FractionPart = atoi(*(splitedStr + i));
|
||||
outData[8] = FractionPart & 0xFF;
|
||||
//log_info("getUIBCGenericRotatePacket FractionPart=[%d]\n", FractionPart);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(*(splitedStr + i));
|
||||
}
|
||||
|
||||
free(splitedStr);
|
||||
}
|
||||
//hexdump(outData, uibcBodyLen);
|
||||
uibcmessage->m_DataValid = true;
|
||||
uibcmessage->m_PacketDataLen = uibcBodyLen;
|
||||
}
|
||||
|
||||
|
||||
char** str_split(char* pStr, const char* pDelim, size_t* size) {
|
||||
char** result = 0;
|
||||
size_t count = 0;
|
||||
char* tmp = pStr;
|
||||
char* tmpStr = NULL;
|
||||
char* last_comma = 0;
|
||||
|
||||
asprintf(&tmpStr, "%s", pStr);
|
||||
|
||||
/* Count how many elements will be extracted. */
|
||||
while (*tmp) {
|
||||
if (*pDelim == *tmp) {
|
||||
count++;
|
||||
last_comma = tmp;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
/* Add space for trailing token. */
|
||||
count += last_comma < (pStr + strlen(pStr) - 1) ? 1 : 0;
|
||||
|
||||
result = (char**)malloc(sizeof(char*) * count);
|
||||
|
||||
*size = count;
|
||||
|
||||
tmp = tmpStr = strdup(pStr);
|
||||
size_t idx = 0;
|
||||
char* token;
|
||||
while ((token = strsep(&tmp, pDelim)) != NULL) {
|
||||
* (result + idx++) = strdup(token);
|
||||
}
|
||||
free(tmpStr);
|
||||
return result;
|
||||
}
|
48
src/uibc/miracle-uibcctl.h
Normal file
48
src/uibc/miracle-uibcctl.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
|
||||
#ifndef MIRACLE_UIBCCTL_H
|
||||
#define MIRACLE_UIBCCTL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include<arpa/inet.h>
|
||||
#include <math.h>
|
||||
#include "shl_log.h"
|
||||
|
||||
typedef enum {
|
||||
GENERIC_TOUCH_DOWN = 0,
|
||||
GENERIC_TOUCH_UP,
|
||||
GENERIC_TOUCH_MOVE,
|
||||
GENERIC_KEY_DOWN,
|
||||
GENERIC_KEY_UP,
|
||||
GENERIC_ZOOM,
|
||||
GENERIC_VERTICAL_SCROLL,
|
||||
GENERIC_HORIZONTAL_SCROLL,
|
||||
GENERIC_ROTATE
|
||||
} MessageType;
|
||||
|
||||
typedef struct {
|
||||
char* m_PacketData;
|
||||
size_t m_PacketDataLen;
|
||||
bool m_DataValid;
|
||||
} UibcMessage;
|
||||
|
||||
UibcMessage buildUibcMessage(MessageType type, const char* inEventDesc, double widthRatio, double heightRatio);
|
||||
|
||||
static char** str_split(char* pStr, const char* pDelim, size_t* size);
|
||||
|
||||
void getUIBCGenericTouchPacket(const char *inEventDesc, UibcMessage* uibcmessage, double widthRatio, double heightRatio);
|
||||
void getUIBCGenericKeyPacket(const char *inEventDesc, UibcMessage* uibcmessage);
|
||||
void getUIBCGenericZoomPacket(const char *inEventDesc,UibcMessage* uibcmessage);
|
||||
void getUIBCGenericScalePacket(const char *inEventDesc, UibcMessage* uibcmessage);
|
||||
void getUIBCGenericRotatePacket(const char *inEventDesc, UibcMessage* uibcmessage);
|
||||
|
||||
void hexdump(void *_data, size_t len);
|
||||
void binarydump(void *_data, size_t len);
|
||||
|
||||
int sendUibcMessage(UibcMessage* uibcmessage, int sockfd);
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue