Inial commit
This commit is contained in:
commit
e7656962d2
3 changed files with 169 additions and 0 deletions
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
cmake_minimum_required(VERSION 3.21)
|
||||||
|
|
||||||
|
project(onkioriclient LANGUAGES C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 17)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} main.c)
|
||||||
|
install(FILES onkiori.service DESTINATION /etc/systemd/system)
|
||||||
151
main.c
Normal file
151
main.c
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/hidraw.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct key
|
||||||
|
{
|
||||||
|
int linux_code;
|
||||||
|
int onkio_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct key keys[] =
|
||||||
|
{
|
||||||
|
{KEY_PLAY, 3471},
|
||||||
|
{KEY_V, 3983},
|
||||||
|
{KEY_Q, 911},
|
||||||
|
{KEY_A, 943},
|
||||||
|
{KEY_FASTFORWARD, 2959},
|
||||||
|
{KEY_REWIND, 1935},
|
||||||
|
{-1, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int register_uinput_device(const char* uinputdev, const char* devname, uint16_t vid, uint16_t pid)
|
||||||
|
{
|
||||||
|
int fd = open(uinputdev, O_RDWR);
|
||||||
|
if(fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
|
struct uinput_setup dev = {};
|
||||||
|
size_t len = strlen(devname);
|
||||||
|
if(len > UINPUT_MAX_NAME_SIZE)
|
||||||
|
len = UINPUT_MAX_NAME_SIZE;
|
||||||
|
strncpy(dev.name, devname, len);
|
||||||
|
|
||||||
|
dev.id.bustype = BUS_VIRTUAL;
|
||||||
|
dev.id.vendor = vid;
|
||||||
|
dev.id.product = pid;
|
||||||
|
|
||||||
|
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
||||||
|
|
||||||
|
for(size_t i = 0; keys[i].linux_code > 0; ++i)
|
||||||
|
ioctl(fd, UI_SET_KEYBIT, keys[i].linux_code);
|
||||||
|
|
||||||
|
int ret = ioctl(fd, UI_DEV_SETUP, &dev);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = ioctl(fd, UI_DEV_CREATE);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if(argc < 2)
|
||||||
|
{
|
||||||
|
printf("usage: %s [BIND ADDR]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* addrstr = argv[1];
|
||||||
|
|
||||||
|
int uinputfd = register_uinput_device("/dev/uinput", "ONKIO RI", 0xfefe, 0xfefe);
|
||||||
|
|
||||||
|
if(uinputfd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not create uinput device: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if(socketfd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not create socket device: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
in_addr_t addr = inet_addr(addrstr);
|
||||||
|
struct sockaddr_in sockaddr = {.sin_family = AF_INET, .sin_port = htons(40586), .sin_addr = {.s_addr = INADDR_ANY}};
|
||||||
|
int ret = bind(socketfd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr));
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not bind to socket: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[65] = {};
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
ret = read(socketfd, buffer, 64);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Could not read from to socket: %s\n", strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const char* header = "RI_MESSAGE: ";
|
||||||
|
if(strncmp(header, buffer, strlen(header)) == 0 && ret > strlen(header)+1)
|
||||||
|
{
|
||||||
|
int code = atoi(buffer+strlen(header));
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for(size_t i = 0; keys[i].linux_code > 0; ++i)
|
||||||
|
{
|
||||||
|
if(keys[i].onkio_code == code)
|
||||||
|
{
|
||||||
|
struct input_event ev = {};
|
||||||
|
ev.type = EV_KEY;
|
||||||
|
ev.code = keys[i].linux_code;
|
||||||
|
ev.value = 1;
|
||||||
|
if(write(uinputfd, &ev, sizeof(ev)) != sizeof(ev))
|
||||||
|
return -1;
|
||||||
|
ev.value = 0;
|
||||||
|
if(write(uinputfd, &ev, sizeof(ev)) != sizeof(ev))
|
||||||
|
return -1;
|
||||||
|
gettimeofday(&ev.time, NULL);
|
||||||
|
ev.type = EV_SYN;
|
||||||
|
ev.code = SYN_REPORT;
|
||||||
|
ev.value = 0;
|
||||||
|
if(write(uinputfd, &ev, sizeof(ev)) != sizeof(ev))
|
||||||
|
return -2;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Got %s code %i\n", found ? "known" : "unkown", code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(uinputfd);
|
||||||
|
close(socketfd);
|
||||||
|
}
|
||||||
10
onkiori.service
Normal file
10
onkiori.service
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Emulates a keyboard based on the codes sent by the OnkioRI device
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/onkioriclient 10.0.0.1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Loading…
Add table
Add a link
Reference in a new issue