Snippet: Prevent USB devices from sleeping
This little C program prevents USB devices from sleeping while under aggressive
power saving settings. Grab your USB devices from lsusb
and throw your
mouse/keyboard into the devices-array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
/*
Throw into Makefile & compile with sudo make:
no_mouse_sleep: no-mouse-sleep.c
gcc no-mouse-sleep.c -o no_mouse_sleep -Wall -Wextra -Werror
sudo chown root:root no_mouse_sleep
sudo chmod +s no_mouse_sleep
*/
const char *dev_path = "/sys/bus/usb/devices/";
// Find your device with `lsusb`
const char *devices[] = {
"046d", "c31c", // Logitech, Inc. Keyboard K120
"8564", "4000", // Transcend Information, Inc. RDF8
"046d", "c069", // Logitech, Inc. M-U0007 [Corded Mouse M500]
};
int main() {
if(setuid(0)) {
perror("Couldn't set uid to root");
return 1;
}
if(setgid(0)) {
perror("Couldn't set gid to root");
return 1;
}
DIR *dp;
struct dirent *ep;
dp = opendir(dev_path);
if (!dp) {
perror("Couldn't open usb device list");
return 1;
}
while ((ep = readdir(dp))) {
if(ep->d_name && ep->d_name[0] != '.') {
char product[5] = {0}, vendor[5] = {0};
size_t path_len = sizeof(char) * (strlen(dev_path) + strlen(ep->d_name) + strlen("/power/control") + 1);
char *path = calloc(path_len + 1, 1);
snprintf(path, path_len, "%s%s/idProduct", dev_path, ep->d_name);
FILE *fp = fopen(path, "r");
if (!fp) {
free(path);
continue;
}
fread(product, 4, sizeof(char), fp);
fclose(fp);
snprintf(path, path_len, "%s%s/idVendor", dev_path, ep->d_name);
fp = fopen(path, "r");
if (!fp) {
free(path);
continue;
}
fread(vendor, 4, sizeof(char), fp);
fclose(fp);
for (unsigned int i = 0; i < sizeof(devices)/sizeof(devices[0])/2; i++) {
if (!strcmp(vendor, devices[i*2]) && !strcmp(product, devices[i*2+1])) {
snprintf(path, path_len, "%s%s/power/control", dev_path, ep->d_name);
fp = fopen(path, "w");
if (!fp) {
perror("Couldn't open power control file for writing");
continue;
}
printf("Disabling autosuspend for %s:%s\n", vendor, product);
fwrite("on\n", 4, sizeof(char), fp);
fclose(fp);
}
}
free(path);
}
}
closedir(dp);
return 0;
}