-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added touchpad script and basic c implementation
- Loading branch information
Showing
5 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"files.associations": { | ||
"select.h": "c" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |