C/C++ Modify keyboard light values

In a C program, is it possible to turn on and off the Num Lock, Caps Lock, and Scroll Lock lights? I'm at a virtual console; X is not running on this system.

It doesn't matter to me whether this actually has the same effect as pressing the Num Lock, Caps Lock, and Scroll Lock keys; I care only about flashing the lights.


/* ... */
#include <sys/ioctl.h>
#include <sys/kbio.h>
/* ... */

int tty = open("/dev/ttyv8", O_RDONLY);
int state;
ioctl(tty, KDGETLED, &state);
ioctl(tty, KDSETLED, state | LED_CAP);
/* ... */

This should enable the Caps Lock LED. Look at /usr/include/sys/kbio.h for the other LEDs and substitute /dev/ttyv8 with your current tty.
I had some fun with your idea
Actually, I have a confession to make. I was incredibly lazy when posing the original question, because I could have discovered the answer myself. See, I'm not starting from scratch. Being part of the systemd diaspora, I'm porting an application to FreeBSD. I wasn't aware when I asked the question that this application uses those same ioctls, but they're in a different include file on That Other System. I could have simply guessed that this might be the case, done this on FreeBSD:
grep -lR SETLED /usr/include 2> /dev/null
and saved you all this trouble. My apologies.

Anyway, this application runs on a dedicated box with a dedicated monitor with a screen blanking interval of 60 seconds. The two or three times a week that the box needs my attention, it flashes the LEDs in one pattern or another. It also wakes up the screen, and keeps it awake. Further exploration of this topic yields the following FreeBSD-specific info:
  1. As on Linux, you don't need to be root to flash the LEDs.
  2. As on Linux, you can simply use /dev/tty.
  3. Unlike on Linux, as soon as you use an <Alt>Fn key to move to a different virtual console, the artificial values of the LEDs disappear, even if you come back to the original virtual terminal. On Linux, they also disappear, but they reappear if you come back to the original virtual terminal. I consider the Linux way a little better, but it doesn't make much difference in my situation.
  4. Unlike on Linux, flashing the LEDs does not wake up the screen and reset the screen blanking timeout. I can work around that on FreeBSD by using system(3) calls in the C code to do vidcontrol -t off (and then turn it back on again right away).
The application, by the way, is a security layer for my house's POTS line, written half in C and half in LISP. We get no unwanted telephone ringing around here. People on our "A" list are handled as with a regular phone, including gathering messages (and flashing the LEDs and waking up the screen) if we're not here. Other people (once they pass the Turing test so we know they're not robocallers) are allowed to leave a message (which flashes the LEDs and wakes up the screen), but the phone doesn't physically ring. Robocallers aren't even allowed to leave a message. And known obnoxious numbers are handled by not even picking up the line. From the other end, it seems like our phone is ringing and ringing.

Hardware is from Digium, the provider of record for those who use Asterisk. I use their drivers (the dahdi package), and tiny chunks of Asterisk code for handling low-level stuff like DTMF tone recognition.

My phone is mine. I get to tame it any way I want.
My thinkpad has a light on the F1 key (meaning mute), which is constantly on. There seems to be no LED_... value for this in /usr/include/sys/kbio.h. Is there a way to switch it off?