Last active
May 20, 2023 22:53
-
-
Save hyc/0d3d4cc4d554c79fa3e33c79c3271faf to your computer and use it in GitHub Desktop.
Toggle keyboard backlight using OpenRGB on Lenovo Legion 7
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
/* Author: Howard Chu <[email protected]> 2023-05-20 | |
* | |
* monitor keyboard activity and toggle keyboard backlight | |
* for Lenovo Legion 7 gen6. | |
*/ | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <poll.h> | |
#include <signal.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <sys/ioctl.h> | |
#include <linux/kd.h> | |
#define DEFPORT 6742 | |
#define NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS 1051 /* OpenRGB NetworkProtocol.h */ | |
#define ZONECOLORS 143 | |
static char dummybuf[8192]; | |
unsigned short port = DEFPORT; | |
struct sockaddr_in sa; | |
int kbdfd; | |
int oldkbmode; | |
/** @brief How many milliseconds before turning off kbd light */ | |
#ifndef IDLE_MSEC | |
#define IDLE_MSEC 7000 | |
#endif | |
typedef struct header { | |
char magic[4]; | |
unsigned int dev_idx; | |
unsigned int id; | |
unsigned int size; | |
} header; | |
typedef struct msgdata { | |
unsigned int size2; | |
unsigned int zone; | |
unsigned short num; | |
unsigned short color[ZONECOLORS*2]; | |
} msgdata; | |
typedef struct msgpkt { | |
header hdr; | |
msgdata dat; | |
} msgpkt; | |
static void die(int x) | |
{ | |
ioctl(kbdfd, KDSKBMODE, oldkbmode); | |
exit(1); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
struct pollfd pfd; | |
int rc, blfd, scfd; | |
int brt, timeout, prev = -1; | |
int maxbrt; | |
char bm[2] = "0\n"; | |
msgpkt msg = {{{'O','R','G','B'},0,NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS, sizeof(msgdata)}, | |
{sizeof(msgdata),0,ZONECOLORS}}; | |
/* Get max brightness */ | |
scfd = open("/sys/class/backlight/amdgpu_bl1/max_brightness", O_RDONLY); | |
read(scfd, dummybuf, sizeof(dummybuf)); | |
maxbrt = atoi(dummybuf); | |
close(scfd); | |
scfd = open("/sys/class/backlight/amdgpu_bl1/brightness", O_RDONLY); | |
/* Connect to OpenRGB SDK */ | |
blfd = socket(PF_INET, SOCK_STREAM, 0); | |
sa.sin_family = AF_INET; | |
sa.sin_port = htons(port); | |
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
if (connect(blfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { | |
perror("connect"); | |
exit(1); | |
} | |
/* pfd.fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY); */ | |
pfd.fd = open("/dev/tty0", O_RDONLY); | |
kbdfd = pfd.fd; | |
pfd.events = POLLIN; | |
ioctl(kbdfd, KDGKBMODE, &oldkbmode); | |
signal(SIGINT, die); | |
ioctl(kbdfd, KDSKBMODE, K_RAW); | |
timeout = IDLE_MSEC; | |
while (1) { | |
rc = poll(&pfd, 1, timeout); | |
/* Kbd colors range from 0 to 255. | |
* Screen brightness ranges from 0 to 255. | |
* Consider making the keyboard brightness | |
* depend on the screen brightness. | |
* | |
* Assume 255 means working in a bright room. | |
* In that case, leave the kbd light off. | |
* Otherwise, use screen brightness as kbd brightness. | |
*/ | |
if (rc) { | |
/* got keyboard input, flush it all and | |
* wait for the next event. Also check | |
* the screen brightness and set the kbd | |
* backlight accordingly. | |
*/ | |
read(pfd.fd, dummybuf, sizeof(dummybuf)); | |
timeout = IDLE_MSEC; | |
read(scfd, dummybuf, sizeof(dummybuf)); | |
lseek(scfd, 0, SEEK_SET); | |
brt = atoi(dummybuf); | |
if (brt == maxbrt) { | |
brt = 0; | |
} | |
} else { | |
/* soft fade out */ | |
brt >>= 1; | |
timeout = brt ? 100 : -1; | |
/* once we've gotten a timeout, turn off | |
* kbd backlight and wait forever for | |
* the next keypress | |
*/ | |
} | |
if (brt == prev) | |
continue; | |
{int i; | |
unsigned short *c = msg.dat.color; | |
for (i=0; i<ZONECOLORS; i++) { | |
*c++ = brt<<8; | |
*c++ = brt; | |
} | |
} | |
write(blfd, &msg, sizeof(msg)); | |
prev = brt; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment