Skip to content

Commit

Permalink
Added touchpad script and basic c implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
LinusCDE committed Feb 23, 2019
1 parent a74e96e commit ae1a8fc
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 0 deletions.
87 changes: 87 additions & 0 deletions pcWacomToMouseTouchpad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
'''
Meant to run on your PC.
Receives data generated by rmServerWacomInput.py,
moves the mouse and presses accordingly.
Acts like a touchpad.
'''


import socket
import struct
from pynput.mouse import Button, Controller

mouse = Controller()

# ----------
# Config:

ONLY_DEBUG = False # Only show data. Don't move mouse

CLICK_PRESSURE = 1000
RELEASE_PRESSURE = 100

MAX_DIST = 20 # Max is 50
SPEED = 1.0
INVERT_X = True # Can be used to change orientation
INVERT_Y = True
# ----------


WACOM_WIDTH = 15725 # Values just checked by drawing to the edges
WACOM_HEIGHT = 20967 # ↑


# Source: https://github.com/canselcik/libremarkable/blob/master/src/input/wacom.rs
EV_SYNC = 0
EV_KEY = 1
EV_ABS = 3
WACOM_EVCODE_PRESSURE = 24
WACOM_EVCODE_DISTANCE = 25
WACOM_EVCODE_XTILT = 26
WACOM_EVCODE_YTILT = 27
WACOM_EVCODE_XPOS = 0
WACOM_EVCODE_YPOS = 1

lastXPos = None
lastYPos = None
lastXTilt = -1
lastYTilt = -1
lastDistance = -1
lastPressure = -1

mouseButtonPressed = False

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('10.11.99.1', 33333))

while True:
evDevType, evDevCode, evDevValue = struct.unpack('HHi', client.recv(8))
if evDevType == EV_ABS:
if evDevCode == WACOM_EVCODE_XPOS:
if lastDistance < MAX_DIST and lastXPos is not None:
xDist = (evDevValue - lastXPos) * (-SPEED if INVERT_X else SPEED)
mouse.move(xDist, 0)
lastXPos = evDevValue
elif evDevCode == WACOM_EVCODE_YPOS:
if lastDistance < MAX_DIST and lastYPos is not None:
yDist = (evDevValue - lastYPos) * (-SPEED if INVERT_Y else SPEED)
mouse.move(0, yDist)
lastYPos = evDevValue
elif evDevCode == WACOM_EVCODE_XTILT:
lastXTilt = evDevValue
elif evDevCode == WACOM_EVCODE_YTILT:
lastYTilt = evDevValue
elif evDevCode == WACOM_EVCODE_DISTANCE:
lastDistance = evDevValue
elif evDevCode == WACOM_EVCODE_PRESSURE:
if not ONLY_DEBUG:
if not mouseButtonPressed and evDevValue > CLICK_PRESSURE:
mouse.press(Button.left)
mouseButtonPressed = True
elif mouseButtonPressed and evDevValue <= RELEASE_PRESSURE:
mouse.release(Button.left)
mouseButtonPressed = False

lastPressure = evDevValue
5 changes: 5 additions & 0 deletions server_in_c/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"select.h": "c"
}
}
8 changes: 8 additions & 0 deletions server_in_c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
rebuild:
make clean build

clean:
rm -f rmServeWacomInput

build:
gcc rmServeWacomInput.c -o rmServeWacomInput
16 changes: 16 additions & 0 deletions server_in_c/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Here is the basic c implementation of the rmServer

# Compile

- Either use a transpiler
- Or just take a RaspberryPi

I'm not experienced with [the transpiler for the reMarkable](https://remarkablewiki.com/devel/qt_creator). I've installed it, but can't compile anything due to missing includes.

## Using the RaspberryPi

- Get the c-file onto your RaspberryPi
- Ensure you have gcc and linux-headers installed
- Compile with the binary using `make`
- Copy the binary (rmServeWacomInput) to the reMarkable and execute it
- Run the client on your computer
138 changes: 138 additions & 0 deletions server_in_c/rmServeWacomInput.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
This sourcecode was hacked together from those two sources:
https://www.geeksforgeeks.org/socket-programming-cc/
https://stackoverflow.com/q/22209267
The Server works like the python script but stops working after one connection.
I don't have any experience with os-sockets and evdev, so if somebody wants fix this
or just clean this mess up, he's welcome to submit push requests.
*/

// Server:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>

// EvDev:
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termios.h>
#include <signal.h>

// Own packet creation:
#include <stdint.h>


#define SERVER_PORT 33333

int main(int argc, char const *argv[])
{
// ------------------------------
// ServerSocket setup:
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};

// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port SERVER_PORT
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( SERVER_PORT );

// Forcefully attaching socket to the port SERVER_PORT
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// ------------------------------


// ------------------------------
// EV-Dev setup:
struct input_event ev;
int fevdev = -1;
int result = 0;
int size = sizeof(struct input_event);
int rd;
int value;
char name[256] = "Unknown";
char *device = "/dev/input/event0";

// ------------------------------

// Getting new client:
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {
perror("accept");
exit(EXIT_FAILURE);
}

// Example transmission:
/*
int valread = read( new_socket , buffer, 1024);
printf("%s\n",buffer );
char *hello = "Hello from server";
send(new_socket , hello , strlen(hello) , 0 );
printf("Hello message sent\n");*/

// Open evdev:
fevdev = open(device, O_RDONLY);
if (fevdev == -1) {
printf("Failed to open event device.\n");
exit(1);
}
printf("Opened evdev.\n");

while(1) {
// Read evdev:
if ((rd = read(fevdev, &ev, size)) < size) {
printf("Lost input device. Exiting.\n");
close(fevdev);
return 1;
}

// Debug:
//printf("Type: %d, Code: %d, Value: %d\n", ev.type, ev.code, ev.value);

// May not be the native values but are needed in this format anyway:
// Create packet as in python struct fmt 'HHi'
uint16_t evType = (uint16_t) ev.type;
uint16_t evCode = (uint16_t) ev.code;
int32_t evValue = (int32_t) ev.value;

uint8_t packet[8];
memcpy(packet, &evType, 2);
memcpy(packet + 2, &evCode, 2);
memcpy(packet + 4, &evValue, 4);

// Send packet:
send(new_socket, packet, 8, MSG_DONTWAIT);
}

printf("Exiting...");
close(fevdev);
return 0;
}

0 comments on commit ae1a8fc

Please sign in to comment.