keyboards are 2 layers of plastic film with tiny electric contact, separated by a third layer of plastic film with holes on the spot of every single key.
when you press a key, the top and bottom plastic are pressed against one another inside the hole of the middle layer, and the electronic signal going from the top to the bottom layer tells your computer that the key is pressed.
problem is: separation is the same as an average good quality book paper sheet, or maybe the same as the aluminum sheet that makes a soda or beer can. also, the electricity that goes trough your keyboard is extremely tiny, and sensors are VERRY sensible, so your air battery can lasts longer.
So even if you have a single hair touching those circuits, your keyboard would "break" the same way it breaks when you spill coffee or whatever liquid; even after the liquid dries, the coffee and the sugar are probably still there "pressing" your alt key.
solution: (this will probably void any warranty) open your computer carefully, remove the keyboard, dismantle all keys one by one, separate the plastic layers with surgical precision so you don't cause any ruptures to the electric "wires", then wash everything with a lot of water and very little mild soap, take extra care to remove ALL the soap, leave everything to dry in the sun (you know electronic components don't like humidity, right?) assemble everything together with "just-washed" oil free hands (don't touch the inner part of the sensors now).
Doing all this, if you have any luck your keyboard might work 100% again... or maybe you might make it stop working entirely, who knows? =)
if you have some money, then backup you computer, go to the applestore and tell them you want to buy a new keyboard, because you broke the current one.
they shall give you a brand new (refurbished?) one, and charge you only the new keyboard. or they might give the same one back to you, who knows? haha.
I've figured out how to do this. In short, you must send a "Feature Report" consisting of the bytes 0x9, 0x0, 0x0, 0x0
to the appropriate hidraw device as root.
You can find the right hidraw device with this command:
dmesg | grep Apple | grep Keyboard | grep input0 | tail -1 | sed -e 's/.*hidraw\([[:digit:]]\+\).*/\/dev\/hidraw\1/'
The code to send the magic control packet is below. Compiles with gcc, takes the hidraw device as parameter. So the entire flow is:
- save the code below as
disable-capslock-delay.c
gcc -o disable-capslock-delay disable-capslock-delay.c
HIDDEVICE=$(dmesg | grep Apple | grep Keyboard | grep input0 | tail -1 | sed -e 's/.*hidraw\([[:digit:]]\+\).*/\/dev\/hidraw\1/')
sudo ./disable-capslock-delay $HIDDEVICE
Steps 3 and 4 have to be done every time you reboot (or unplug and re-plug the keyboard); you can put them into /etc/rc.local
(or your distro's equivalent) to execute them at boot (you don't need sudo
in that case; and you might want to move the compiled binary into /usr/local/sbin/
or something).
I've put in some safety checks for vendor ID, device ID, and report descriptor length. You may have to change the latter two if your model differs from mine.
#include <linux/hidraw.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
if (argc != 2 || strcmp(argv[1], "-h") == 0) {
printf("Pass a hidraw device as the first and only parameter!\n");
printf("You may find the right device with:\n");
printf(" dmesg | grep Apple | grep Keyboard | grep input0 | tail -1 | "
"sed -e 's/.hidraw\([[:digit:]]\+\)./\/dev\/hidraw\1/'\n");
return 1;
}
int fd, i, res, desc_size = 0;
char buf[256];
struct hidraw_devinfo info;
char *device = argv[1];
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 Report Descriptor Size
res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
if (res < 0) {
perror("HIDIOCGRDESCSIZE");
}
if (desc_size != 75) {
printf("Error: unexpected descriptor size %d; you've probably got "
"the wrong hidraw device!\n", desc_size);
return 1;
}
// Get Raw Info
res = ioctl(fd, HIDIOCGRAWINFO, &info);
if (res < 0) {
perror("HIDIOCGRAWINFO");
} else {
if (info.vendor != 0x05ac) {
printf("Error: Wrong vendor ID, make sure you got the right "
"hidraw device!\n");
return 1;
}
if (info.product != 0x0250) {
printf("Warning: Unknown product ID 0x%x!\n", info.product);
}
}
// 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] = 0x00; // 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");
} else {
printf("HID Feature Report (after change):\n\t");
for (i = 0; i < res; i++) printf("%hhx ", buf[i]);
puts("\n");
}
close(fd);
return 0;
}
Best Answer
Resetting the System Management Controller on my MacBook seems to have solved this problem.