Re: kblevel - set keyboard illumination directly
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 I2CCHIPuni-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(reg, 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; }
Re: kblevel - set keyboard illumination directly
On Tue, 20 Jun 2006 01:44:56 +1000 Paul Collins [EMAIL PROTECTED] wrote: By the way, could somebody test the 255 brightness steps stuff in pbbuttonsd? It works in theory, but I would like to have the confirmation. ;-) The code is in CVS on sourceforge.net Thanks and Regards Matthias -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: kblevel - set keyboard illumination directly
I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. IIRC there's been lmud to do the very same thing. Michael -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 01:44 +1000, Paul Collins wrote: I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. One other thing I'd love to see but don't have time to implement at the moment would be having this as a hal addon exposing it there and also polling the ambient light sensors and exposing those events via hal. johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 01:44 +1000, Paul Collins wrote: I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. Of course, I'm the one complaining all the time... If the error code is 'permission denied' (-EACCESS) it could really print that. I just tried running it as non-root for a while until I noticed ;) johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
Johannes Berg [EMAIL PROTECTED] writes: On Tue, 2006-06-20 at 01:44 +1000, Paul Collins wrote: I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. Cool. One thing I would want to add is support for finding the address and bus directly via open firmware instead of that stupid 4..260 loop, you may look at http://git.sipsolutions.net/of-lib.git/ for a WIP library to access the device-tree. I was able to use this code to find the lmu-controller node and read the address from 'reg' - looks like it's the value shifted right one bit. (An old posting[1] does it similarly.) But I can't work out how to get the bus number (probed as 8 on my machine). The linked patch tries to use the last bit of 'reg', but that can't be right. [1] http://lists.debian.org/debian-powerpc/2004/01/msg01042.html -- Paul Collins Melbourne, Australia Dag vijandelijk luchtschip de huismeester is dood -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 17:41 +1000, Paul Collins wrote: I was able to use this code to find the lmu-controller node and read the address from 'reg' - looks like it's the value shifted right one bit. (An old posting[1] does it similarly.) Yes, that's because Apple treats the rw bit which is in the first byte as being there. That's expected, look at *any* kernel i2c code we use :) But I can't work out how to get the bus number (probed as 8 on my machine). The linked patch tries to use the last bit of 'reg', but that can't be right. Indeed, that can't be right, you'll have to crawl /sys: /sys/class/i2c-dev/*/name The LMU node on my tree is below [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] which is the i2c bus named uni-n 0. (combined from [EMAIL PROTECTED]@0 as far as I can tell). Maybe we can convince benh to add a property to the i2c busses that tell which path they have in the device tree. Ben? johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 10:26 +0200, Johannes Berg wrote: The LMU node on my tree is below [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] which is the i2c bus named uni-n 0. (combined from [EMAIL PROTECTED]@0 as far as I can tell). Maybe we can convince benh to add a property to the i2c busses that tell which path they have in the device tree. Ben? I suppose we could ... Ben. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 18:39 +1000, Benjamin Herrenschmidt wrote: The LMU node on my tree is below [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] which is the i2c bus named uni-n 0. (combined from [EMAIL PROTECTED]@0 as far as I can tell). Maybe we can convince benh to add a property to the i2c busses that tell which path they have in the device tree. Ben? I suppose we could ... We may still want to use this on older kernels though. If I knew how to add arbitrary sysfs attributes I'd submit a patch right away, but I don't, and I don't have time to research it right now. Anyway, I checked the code, and it looks like my analysis wasn't quite correct, it seems to use snprintf(..., %s %d, parentname, channel) but channel isn't assigned based on the i2c-bus' reg property but just an arbitrary number, so we'd have to probe both uni-n busses. Which is fine, still *much* better than probing all of them. johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
Johannes Berg [EMAIL PROTECTED] writes: Indeed, that can't be right, you'll have to crawl /sys: /sys/class/i2c-dev/*/name The LMU node on my tree is below [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] which is the i2c bus named uni-n 0. (combined from [EMAIL PROTECTED]@0 as far as I can tell). Maybe we can convince benh to add a property to the i2c busses that tell which path they have in the device tree. Ben? It's in my device-tree as [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] I also have [EMAIL PROTECTED] and [EMAIL PROTECTED] in there, but there's no uni-n 2 in /sys/class/i2c-dev/*/name, so I guess simply sorting by @foo isn't the way to map to the i2c-dev name attributes. -- Paul Collins Melbourne, Australia Dag vijandelijk luchtschip de huismeester is dood -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 18:50 +1000, Paul Collins wrote: It's in my device-tree as [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] I also have [EMAIL PROTECTED] and [EMAIL PROTECTED] in there, but there's no uni-n 2 in /sys/class/i2c-dev/*/name, so I guess simply sorting by @foo isn't the way to map to the i2c-dev name attributes. Yeah, I was wrong, see my other mail. Btw, it's in my device-tree as [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] with a compatible 'lmu-controller' property. johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
Johannes Berg [EMAIL PROTECTED] writes: On Tue, 2006-06-20 at 18:50 +1000, Paul Collins wrote: It's in my device-tree as [EMAIL PROTECTED]/[EMAIL PROTECTED]/[EMAIL PROTECTED] I also have [EMAIL PROTECTED] and [EMAIL PROTECTED] in there, but there's no uni-n 2 in /sys/class/i2c-dev/*/name, so I guess simply sorting by @foo isn't the way to map to the i2c-dev name attributes. Yeah, I was wrong, see my other mail. No worries. I have sysfs-based probing code working now. 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. -- Paul Collins Melbourne, Australia Dag vijandelijk luchtschip de huismeester is dood -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: kblevel - set keyboard illumination directly
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. johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
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 || || 7654 3210 |-| ^-- 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);
kblevel - set keyboard illumination directly
I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. I've tried to preserve PowerBook5,8/5,9 support, but I only have a PowerBook5,4 here so I can't test it. Thanks of course are due to Matthias Grimm for writing the original pbbuttonsd code. /* * 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. */ #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 #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)) { 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; } /* * This function tries to find the I2C device that controls the * keyboard illumination and the ambient light sensor used in some * AlBooks. It returns an open fd on success, otherwise a negative * error code. The loop starts with device 4 because that's the * correct device on 17 AlBooks. Device 0 could be falsely detected * because the function uses only circumstantial evidence to detect * the correct device. */ int find_i2c_device(void) { char i2cdevice[20]; char buf[4]; int n; int fd; int rc = -ENODEV; for(n = 4; n 260; ++n) { snprintf(i2cdevice, 19, /dev/i2c-%d, (n 255) ); if ((fd = open (i2cdevice, O_RDWR)) = 0 ) { if (ioctl (fd, I2C_SLAVE, LMU_ADDR) = 0) if (read (fd, buf, 4) == 4) return fd; close (fd); } else if (errno == ENODEV) { rc = -ENODEV; break; } else if (errno == EACCES) { rc = -EACCES; break; } } 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 || || 7654 3210 |-| ^-- 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
Re: kblevel - set keyboard illumination directly
On Tue, 2006-06-20 at 01:44 +1000, Paul Collins wrote: I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. Cool. One thing I would want to add is support for finding the address and bus directly via open firmware instead of that stupid 4..260 loop, you may look at http://git.sipsolutions.net/of-lib.git/ for a WIP library to access the device-tree. I've tried to preserve PowerBook5,8/5,9 support, but I only have a PowerBook5,4 here so I can't test it. Benjamin? johannes signature.asc Description: This is a digitally signed message part
Re: kblevel - set keyboard illumination directly
On Mon, 2006-19-06 at 19:08 +0200, Johannes Berg wrote: On Tue, 2006-06-20 at 01:44 +1000, Paul Collins wrote: I've extracted the keyboard illumination code from pbbuttonsd for my own use. I post it here in case it may be useful to others. Cool. One thing I would want to add is support for finding the address and bus directly via open firmware instead of that stupid 4..260 loop, you may look at http://git.sipsolutions.net/of-lib.git/ for a WIP library to access the device-tree. I've tried to preserve PowerBook5,8/5,9 support, but I only have a PowerBook5,4 here so I can't test it. Benjamin? Works great on the PowerBook5,8. Benjamin signature.asc Description: This is a digitally signed message part