Johannes Berg <[EMAIL PROTECTED]> writes: > On Tue, 2006-06-20 at 20:23 +1000, Paul Collins wrote: > >> > Btw, it's in my device-tree as >> > [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] >> > with a compatible >> > 'lmu-controller' property. >> >> Does this mean that of_find_node_by_name("lmu-controller", 0) will >> return the correct node? I don't know much about device tree stuff. > > No, you'll probably need to do of_find_compatible_node(NULL, NULL, > "lmu-controller") or something like that, if your compatible property > includes 'lmu-controller' too.
Hmm, no of_find_compatible_node or anything like it that I can see in the of-lib I pulled today. And delightfully there doesn't seem to be any 'compatible' property in my lmu-controller node. Anyway, here's the current version with the sysfs-guided I2C probing.
/* * kblevel.c --- control PowerBook keyboard illumination * * Copyright 2002 Matthias Grimm * Copyright 2006 Paul Collins <[EMAIL PROTECTED]> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ /* * This code was taken from Matthias Grimm's pbbuttonsd. * * Aside from the gratuitous style changes, I altered the code to read * the machine type from /proc/device-tree/model insted of * /proc/cpuinfo and added support for 255 brightness levels. * * We now scan sysfs for likely candidates instead of opening every * possible i2c device and trying to see if it responds as we expect * the LMU to. */ #include <dirent.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdarg.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> #include <linux/adb.h> #define ADB_BUFSIZE 32 #define I2C_SLAVE 0x0703 /* TODO: read this from the device tree. */ #define LMU_ADDR 0x42 int get_machine(void) { char buffer[32]; int machine = 0; int n; FILE *f; if ((f = fopen("/proc/device-tree/model", "r"))) { while (fgets(buffer, sizeof buffer, f)) { if (strncmp("PowerBook", buffer, 9) == 0) { machine = (atoi(&buffer[9]) & 0xf) << 4; for (n = 9; buffer[n] != ',' && buffer[n] != '\0'; ++n) ; if (buffer[n] == ',') machine |= atoi(&buffer[n+1]) & 0xf; } break; } } fclose(f); return machine; } int have_i2c_ambient_sensor(int machine) { if ((machine >= 0x51) && (machine <= 0x57)) return 1; return 0; } int have_pmu_ambient_sensor(int machine) { if ((machine >= 0x58) && (machine <= 0x59)) return 1; return 0; } /* Guess whether an i2c device is the LMU by trying to read sensor data. */ int lmu_probe(const char *dev) { char buf[4]; int fd; if ((fd = open(dev, O_RDWR)) < 0) return -1; if (ioctl(fd, I2C_SLAVE, LMU_ADDR) < 0) { close(fd); return -1; } if (read (fd, buf, 4) == 4) { return fd; } else { close(fd); return -1; } } /* Find I2C devices that might be the LMU controller and probe them. */ int find_i2c_device(void) { char buf[48]; DIR *d; struct dirent *de; int rc = -1; int fd; int i; snprintf(buf, sizeof buf - 1, "/sys/class/i2c-dev"); if (d = opendir(buf)) { while (de = readdir(d)) { if (de->d_name[0] == '.') continue; snprintf(buf, sizeof buf, "/sys/class/i2c-dev/%s/name", de->d_name); if ((fd = open(buf, O_RDONLY)) < 0) { continue; } if ((i = read(fd, buf, sizeof buf)) < 0) { close(fd); continue; } if (i >= sizeof buf) { close(fd); continue; } buf[i] = '\0'; if (!(strncmp("uni-n ", buf, 6) == 0)) { close(fd); continue; } snprintf(buf, sizeof buf, "/dev/%s", de->d_name); if ((rc = lmu_probe(buf)) >= 0) { close(fd); goto out; } } } out: if (d) closedir(d); return rc; } int send_pmu_request(int fd, unsigned char *buffer, int params, ...) { va_list list; int n; int x; if (params < 0 || params > 30) return -1; buffer[0] = PMU_PACKET; va_start(list, params); for (x = 0; x < params; ++x) buffer[x + 1] = va_arg(list, int); va_end(list); n = write(fd, buffer, x+1); if ((n != x+1) || (n == -1)) return -1; if ((n = read(fd, buffer, ADB_BUFSIZE)) < 0) return -1; return n; } int set_keyboard_illumination(unsigned short level) { int machine = get_machine(); unsigned char buf[ADB_BUFSIZE]; int fd; if (level > 255) level = 255; if ((have_i2c_ambient_sensor(machine)) && (fd = find_i2c_device()) > 0) { buf[0] = 0x01; /* i2c register */ /* The format appears to be: byte 1 byte 2 |<---->| |<---->| xxxx7654 3210xxxx |<----->| ^-- brightness */ buf[1] = level >> 4; buf[2] = (level & 0x0f) << 4; write(fd, buf, 3); close(fd); return 1; } if (have_pmu_ambient_sensor(machine) && (fd = open("/dev/adb", O_RDWR)) > 0) { send_pmu_request(fd, buf, 4, 0x4f, 0, 0, level); return 1; } return 0; } int main(int argc, char *argv[]) { int level; if (argc == 2) { /* Some special string values. */ if ((strcmp(argv[1], "on") == 0) || (strcmp(argv[1], "full") == 0)) { level = 255; } else if (strcmp(argv[1], "half") == 0) { level = 127; } else if (strcmp(argv[1], "quarter") == 0) { level = 63; } else if (strcmp(argv[1], "off") == 0) { level = 0; } else { level = atoi(argv[1]); } } else { fprintf(stderr, "usage: kblevel [ off | half | quarter | full | on | 0-255 ]\n"); exit(EXIT_FAILURE); } if (!set_keyboard_illumination(level)) { fprintf(stderr, "failed to set keyboard illumination\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
-- Paul Collins Melbourne, Australia Dag vijandelijk luchtschip de huismeester is dood