Code: Select all
cadmoused.c:
// Vibecoded with Google Gemini 3.1 Pro
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/hidraw.h>
#include <errno.h>
#ifndef HIDIOCSFEATURE
#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
#endif
// Max number of simultaneously open hidraw interfaces
#define MAX_ACTIVE_NODES 16
// Target device structure (VID and PID in uppercase)
typedef struct {
const char *vid;
const char *pid;
const char *name;
} TargetDevice;
// YOUR TARGET DEVICES
TargetDevice TARGET_DEVICES[] = {
{"256F", "C658", "CadMouse (Type-C)"},
{"256F", "C652", "CadMouse (Universal Receiver)"}
};
int NUM_TARGETS = sizeof(TARGET_DEVICES) / sizeof(TARGET_DEVICES[0]);
// Initialization payload (Feature Report ID 16)
// Sniffed from win10
// no idiotic scroll accelerator, normal sense.
const unsigned char FEATURE_PAYLOAD[32] = {
16, 0, 48, 0, 1, 0xFF, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 3, 0, 10, 11, 12, 12, 14,
13, 47, 0, 30, 0, 0, 0, 1
};
// Active connection pool
typedef struct {
int fd;
char path[64];
} ActiveNode;
ActiveNode active_nodes[MAX_ACTIVE_NODES];
void init_pool() {
for (int i = 0; i < MAX_ACTIVE_NODES; i++) {
active_nodes[i].fd = -1;
}
}
int main() {
// make systemd logging happy
setvbuf(stdout, NULL, _IOLBF, 0);
init_pool();
printf("CadMouse keepalive daemon started. Monitoring %d target(s)...\n", NUM_TARGETS);
while (1) {
// 1. CHECK DISCONNECTIONS
for (int i = 0; i < MAX_ACTIVE_NODES; i++) {
if (active_nodes[i].fd != -1) {
if (access(active_nodes[i].path, F_OK) == -1) {
printf("Device disconnected: %s\n", active_nodes[i].path);
close(active_nodes[i].fd);
active_nodes[i].fd = -1;
}
}
}
// 2. SCAN FOR NEW CONNECTIONS
DIR *dir;
struct dirent *ent;
if ((dir = opendir("/sys/class/hidraw")) != NULL) {
while ((ent = readdir(dir)) != NULL) {
if (strncmp(ent->d_name, "hidraw", 6) != 0) continue;
char dev_path[64];
snprintf(dev_path, sizeof(dev_path), "/dev/%s", ent->d_name);
// Skip if this interface is already being monitored
int already_active = 0;
for (int i = 0; i < MAX_ACTIVE_NODES; i++) {
if (active_nodes[i].fd != -1 && strcmp(active_nodes[i].path, dev_path) == 0) {
already_active = 1;
break;
}
}
if (already_active) continue;
// Read uevent to extract VID and PID
char sys_path[256];
char uevent_buf[1024];
snprintf(sys_path, sizeof(sys_path), "/sys/class/hidraw/%s/device/uevent", ent->d_name);
FILE *f = fopen(sys_path, "r");
if (!f) continue;
size_t read_bytes = fread(uevent_buf, 1, sizeof(uevent_buf) - 1, f);
uevent_buf[read_bytes] = '\0';
fclose(f);
// Check against our target list
int matched_target_idx = -1;
for (int i = 0; i < NUM_TARGETS; i++) {
if (strstr(uevent_buf, TARGET_DEVICES[i].vid) != NULL &&
strstr(uevent_buf, TARGET_DEVICES[i].pid) != NULL) {
matched_target_idx = i;
break;
}
}
if (matched_target_idx != -1) {
// Find a free slot in the pool
for (int i = 0; i < MAX_ACTIVE_NODES; i++) {
if (active_nodes[i].fd == -1) {
active_nodes[i].fd = open(dev_path, O_RDWR);
if (active_nodes[i].fd >= 0) {
strncpy(active_nodes[i].path, dev_path, sizeof(active_nodes[i].path));
printf("Detected: %s (%s). Applying configuration...\n",
TARGET_DEVICES[matched_target_idx].name, dev_path);
// Send feature payload
int res = ioctl(active_nodes[i].fd, HIDIOCSFEATURE(32), FEATURE_PAYLOAD);
if (res >= 0) {
printf("\t-> SUCCESS: Configuration accepted by %s\n", dev_path);
}
}
break;
}
}
}
}
closedir(dir);
}
// Sleep for 5 seconds to minimize CPU footprint
sleep(5);
}
return 0;
}
$ gcc -O2 cadmoused.c -o cadmoused
$ mkdir -p ~/.local/bin
$ mv cadmoused ~/.local/bin/
$ nano ~/.config/systemd/user/cadmoused.service
cadmoused.service:
[Unit]
Description=3Dconnexion CadMouse Background Keepalive
After=graphical-session.target
[Service]
ExecStart=%h/.local/bin/cadmoused
Restart=always
RestartSec=3
Nice=10
[Install]
WantedBy=default.target
$ systemctl --user daemon-reload
$ systemctl --user enable --now cadmoused.service
$ journalctl --user -u cadmoused.service -f