[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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(&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;
}


Reply to: