On Tue, 20 Jun 2006 01:44:56 +1000 Paul Collins <[EMAIL PROTECTED]> 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; }