Re: kblevel - set keyboard illumination directly
On Tue, 20 Jun 2006 01:44:56 +1000
Paul Collins <paul@briny.ondioline.org> wrote:
> Thanks of course are due to Matthias Grimm for writing the original
> pbbuttonsd code.
Thank you too. I added support for 255 KBD Brightnesslevel in pbbuttons too :-)
I tried to improve your sysfs LMU detection routines and add the OF
stuff to get the LMU address from the device tree. Unfortunately I have
no PowerBook with a LMU built in so I could test it only with device
tree copies other people sent to me.
I don't know how constant OF device tree names are over the different
models and kernel versions. So any feedback would be welcome.
Best Regards
Matthias
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#define OFBASE "/proc/device-tree"
#define SYSI2CDEV "/sys/class/i2c-dev"
#define I2CCHIP "uni-n"
#define I2C_SLAVE 0x0703
int
probeLMU(char *device, int addr)
{
char buffer[4];
int fd, rc = 0;
if ((fd = open(device, O_RDWR)) >= 0) {
if (ioctl(fd, I2C_SLAVE, addr) >= 0) {
if (read (fd, buffer, 4) == 4)
rc = 1;
}
close(fd);
}
return rc;
}
int
addPath(char *path, int maxlen, char *pattern)
{
DIR *dh;
struct dirent *dir;
int rc = 1;
if ((dh = opendir(path))) {
while (dir = readdir(dh)) {
if ((strncmp(dir->d_name, pattern, strlen(pattern)) == 0)) {
strncat(path, "/", maxlen-1);
strncat(path, dir->d_name, maxlen-1);
rc = 0;
break;
}
}
closedir(dh);
}
return rc;
}
int
getLMUAddress()
{
char path[200];
FILE *fd;
long reg;
int n, rc = 0, err = 0;
path[0] = 0; /* terminate path buffer */
strncat(path, OFBASE, sizeof(path)-1);
err += addPath(path, sizeof(path), "uni-n");
err += addPath(path, sizeof(path), "i2c");
err += addPath(path, sizeof(path), "lmu-controller");
strncat(path, "/reg", sizeof(path)-1);
printf("\nOF: '%s'\n", path);
if (err > 0)
printf(" Path incomplete! One or more elements not found.\n");
else if ((fd = fopen(path, "r")) >= 0) {
n = fread(®, sizeof(long), 1, fd);
if (n == 1)
rc = (int) (reg >> 1);
fclose(fd);
}
return rc;
}
int
findI2CDevice(int addr)
{
char buffer[40];
DIR *dh;
FILE *fd;
struct dirent *dir;
int n;
if ((dh = opendir(SYSI2CDEV))) {
while (dir = readdir(dh)) {
if (dir->d_name[0] == '.') continue;
snprintf(buffer, sizeof(buffer), SYSI2CDEV"/%s/name", dir->d_name);
if ((fd = fopen(buffer, "r")) >= 0) {
n = fread(buffer, 1, sizeof(buffer), fd);
if (n > 0 && n < sizeof(buffer)) {
buffer[n-1] = 0;
printf("I2C: '%s', '%s'", dir->d_name, buffer);
if ((strncmp(I2CCHIP" ", buffer, 6) == 0)) {
snprintf(buffer, sizeof(buffer), "/dev/%s", dir->d_name);
if ((probeLMU(buffer, addr)))
printf(" <- this one!");
}
printf("\n");
}
fclose(fd);
}
}
closedir(dh);
}
}
int
main (int argc, char *argv[])
{
int addr;
addr = getLMUAddress();
if (addr) {
printf("LMU: address %x \n", addr);
findI2CDevice(addr);
} else
printf("No LMU found!\n");
return 0;
}
Reply to: