Here is a complete program fixing the issue on both kind of devices. You can pass extra hid devices, it'll apply only to known ones. So you can simply call it as ./a.out /dev/hidraw*
#include <linux/hidraw.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("Pass all devices to configure. For example, like this: %s /dev/hidraw*\n", argv[0]);
int expected_desc_size;
char data_to_set;
for (int argnum=1;argnum<argc;argnum++) {
printf("Trying to configure %s...\n", argv[argnum]);
int fd, i, res, desc_size = 0;
char buf[256];
struct hidraw_devinfo info;
char *device = argv[argnum];
fd = open(device, O_RDWR | O_NONBLOCK);
if (fd < 0) {
perror("Unable to open device");
return 1;
}
memset(&info, 0, sizeof(info));
memset(buf, 0, sizeof(buf));
// Get Raw Info
res = ioctl(fd, HIDIOCGRAWINFO, &info);
if (res < 0) {
perror("HIDIOCGRAWINFO");
return 1;
}
if (info.vendor == 0x05ac) {
printf("Apple device found!\n");
} else {
printf("Not an apple device.\n");
continue;
}
if (info.product == 0x022d) {
printf("We have a 'magic' keyboard\n");
expected_desc_size = 218;
data_to_set = 1;
} else if (info.product == 0x0250) {
printf("We have an 'aluminium' keyboard\n");
expected_desc_size = 75;
data_to_set = 0;
}
else {
printf("Warning: Unknown product ID 0x%x!\n", info.product);
continue;
}
// Get Report Descriptor Size
res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
if (res < 0) {
perror("HIDIOCGRDESCSIZE");
return 1;
}
if (desc_size != expected_desc_size) {
printf("Error: unexpected descriptor size %d; panic'ing", desc_size);
return 1;
}
// Get Feature
buf[0] = 0x09; // Report Number
res = ioctl(fd, HIDIOCGFEATURE(256), buf);
if (res < 0) {
perror("HIDIOCGFEATURE");
} else {
printf("HID Feature Report (before change):\n\t");
for (i = 0; i < res; i++) printf("%hhx ", buf[i]);
puts("\n");
}
// Set Feature
buf[0] = 0x09; // Report Number
buf[1] = data_to_set; // Report data
buf[2] = 0x00; // padding
buf[3] = 0x00; // padding
res = ioctl(fd, HIDIOCSFEATURE(4), buf);
if (res < 0) {
perror("HIDIOCSFEATURE");
} else {
printf("Caps lock delay disabled.\n");
}
// Get Feature
buf[0] = 0x09; // Report Number
res = ioctl(fd, HIDIOCGFEATURE(256), buf);
if (res < 0) {
perror("HIDIOCGFEATURE");
return 1;
}
printf("HID Feature Report (after change):\n\t");
for (i = 0; i < res; i++) printf("%hhx ", buf[i]);
puts("\n");
close(fd);
}
return 0;
}