Hi, I want to use some OF and kernel 2.6 features to improve device probing in pbbuttonsd. Unfortunately I have only an ancient PowerBook so I need your help to test the new routines on as many different machines as possible.
I attached the source code of a short program. You could compile it as follows: $> gcc -o of_probing of_probing.c This program does three things: 1. detecting the machine ID. Any PowerBook user can test this feature. Launch the program and check if the machine ID is correctly detected on your machine. If you don't know which ID your machine have see in $> cat /proc/device-tree/model or $> cat /proc/cpuinfo Tell me if your machine is not correctly identified. PowerBooks before the G3 Pismo will get the dummy ID "1", because Apple started his numbering system just with the Pismo. 2. detecting the LMU I2C address The program looked for the "lmu-controller" in the device tree and read the attached data to find out the I2C address. This test will only have a result, if you have a PowerBook with an ambient light sensor. Otherwise the program won't find an LMU. If your machine definitely has an ambient light sensor and the program won't find it, the device tree path might be wrong. In this case please send me the correct path or an tar archive of /proc/device-tree. 3. detecting of the /dev/i2c device to communicate with the LMU This test reads /sys to find out which i2c devices are available and which one is connected to the "uni-n" controller the LMU is attached to. Each found i2c device will then be checked for the LMU. The program lists all found i2c devices to the console and mark the device with the LMU connected. This test needs the kernel module i2c-dev to be loaded. If not already done, you could load the module with $> modprobe i2c-dev I would appreciate any feedback. Thank you and 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(" OF: '%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 is the LMU device"); } printf("\n"); } fclose(fd); } } closedir(dh); } } int getMachineID() { char buffer[32]; int fd, n, machine = 0; if ((fd = open(OFBASE"/model", O_RDONLY))) { if ((n = read(fd, buffer, sizeof(buffer) - 1)) != -1) { buffer[n] = 0; /* terminate buffer, only to be sure */ if (strncmp("PowerBook", buffer, 9) == 0) { if (buffer[9] == 0) machine = 1; /* Dummy code for pre-Pismo PowerBooks */ else { machine = (atoi(&buffer[9]) & 0xf) << 4; for (n = 9; buffer[n] != ',' && buffer[n] != '\0'; ++n); if (buffer[n] == ',') machine |= atoi(&buffer[n+1]) & 0xf; } } } close(fd); } return machine; } int main (int argc, char *argv[]) { int addr, machine; printf("\nProbing machine...\n"); machine = getMachineID(); if (machine != 0) { printf (" Machine: ID = %x\n", machine); addr = getLMUAddress(); if (addr) { printf(" LMU: I2C address = %x \n", addr); findI2CDevice(addr); } else printf(" LMU: No LMU found!\n"); } else printf (" Machine: This is not a PowerBook\n"); return 0; }