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