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

Re: New I2C and machine probing method



On Sun, 16 Jul 2006 15:45:57 +0200
Matthias Grimm <matthiasgrimm@users.sourceforge.net> wrote:

Thanks a lot for your support so far. I put the new knowledge into a
revised program and attached it again. Changes are:

- There are two known locations for the lmu-controller in the
  device-tree so far. Both are supported now.
- adding I/O error support. To communicate with the LMU the program
  must be run as root. If there was any problem with the device, an
  I/O error message would occur on terminal.
- removing all the silly warnings
- detailed machine identification by name added

I hope you give it another try :-)

 Best Regards
   Matthias

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#define OFBASE     "./device-tree"
#define SYSI2CDEV  "/sys/class/i2c-dev"
#define I2CCHIP    "uni-n"
#define I2C_SLAVE  0x0703
#define OHARE_PMU  9

static char *machines[7][10] = {
	{ "unknown",
	  "PowerBook 3400",                        /* 0,1 */
	  "PowerBook 3500",                        /* 0,2 */
	  "PowerBook Wallstreet (Apr 1998)",       /* 0,3 */
	  NULL, NULL, NULL, NULL, NULL, NULL },
	{ NULL,
	  "PowerBook 101 Lombard (Apr 1999)",      /* 1,1 */
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	{ NULL,
	  "iBook (Feb 2000)",                      /* 2,1 */
	  "iBook FireWire (Sep 2000)",             /* 2,2 */
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	{ NULL,
	  "PowerBook G3 Pismo (Feb 2000)",         /* 3,1 */
	  "PowerBook G4 Titanium (Dec 2000)",      /* 3,2 */
	  "PowerBook G4 Titanium II (Oct 2001)",   /* 3,3 */
	  "PowerBook G4 Titanium III (Apr 2002)",  /* 3,4 */
	  "PowerBook G4 Titanium IV (Nov 2002)",   /* 3,5 */
	  NULL, NULL, NULL, NULL },
	{ NULL,
	  "iBook 2 (May 2001)",                    /* 4,1 */
	  "iBook 2 (May 2002)",                   /* 4,2 */
	  "iBook 2 rev. 2 (Nov 2002)",           /* 4,3 */
	  NULL, NULL, NULL, NULL, NULL, NULL },
	{ NULL,
	  "PowerBook G4 17\" (Mar 2003)",      /* 5,1 */
	  "PowerBook G4 15\" (Sep 2003)",      /* 5,2 */
	  "PowerBook G4 17\" (Sep 2003)",      /* 5,3 */
	  "PowerBook G4 15\" (Apr 2004)",      /* 5,4 */
	  "PowerBook G4 17\" (Apr 2004)",      /* 5,5 */
	  "PowerBook G4 15\" (Feb 2005)",      /* 5,6 */
	  "PowerBook G4 17\" (Feb 2005)",      /* 5,7 */
	  "PowerBook G4 15\" (Oct 2005)",      /* 5,8 */
	  "PowerBook G4 17\" (Oct 2005)" },    /* 5,9 */
	{ NULL,
	  "PowerBook G4 12\" (Jan 2003)",      /* 6,1 */
	  "PowerBook G4 12\" (Sep 2003)",      /* 6,2 */
	  "iBook G4 (Oct 2003)",               /* 6,3 */
	  "PowerBook G4 12\" (Apr 2004)",      /* 6,4 */
	  "iBook G4 (Apr 2004)",               /* 6,5 */
	  NULL,
	  "iBook G4 (Jul 2005)",               /* 6,7 */
	  "PowerBook G4 12\" (Oct 2005)",      /* 6,8 */
	  NULL }
};
	
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);
	} else 
		printf (" %s!", strerror(errno));

	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];
	long reg;
	int fd, n, rc = 0, err = 0;

	path[0] = 0; /* terminate path buffer */
	strncat(path, OFBASE, sizeof(path)-1);
	if ((err = addPath(path, sizeof(path), "uni-n")) == 0)
		if ((err = addPath(path, sizeof(path), "i2c")) == 0)
			if ((err = addPath(path, sizeof(path), "lmu-controller")) != 0)
				if ((err = addPath(path, sizeof(path), "i2c-bus")) == 0)
					err = addPath(path, sizeof(path), "lmu-micro");

	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 = open(path, O_RDONLY)) >= 0) {
		n = read(fd, &reg, sizeof(long));
		if (n == sizeof(long))
			rc = (int) (reg >> 1);
		close(fd);
	}
	return rc;
}

int
findI2CDevice(int addr)
{
	char buffer[40];
	DIR *dh;
	struct dirent *dir;
	unsigned int n;
	int fd;

	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 = open(buffer, O_RDONLY)) >= 0) {
				n = read(fd, buffer, sizeof(buffer));
				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);
						printf("  probing %s ...", buffer);
						if ((probeLMU(buffer, addr)))
							printf(" gotcha, this is the LMU device");
					}
					printf("\n");
				}
				close(fd);
			}
		}
		closedir(dh);
	}
	return 0;
}

int
getMachineID(int pmu)
{
	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)
					/* Dummy codes for pre-Lombard PowerBooks */
					machine = pmu - OHARE_PMU + 1;
				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;
}

const char*
getMachineName(int mid)
{
	unsigned int x, y;
	
	x = mid >> 4 & 0x0f;
	y = mid & 0xf;
	if (x < 7 && y < 10 && machines[x][y] != NULL)
		return machines[x][y];
	else
		return machines[0][0];
}

int
main (void)
{
	int addr, mid;

	printf("\nProbing machine...\n");
	
	mid = getMachineID(11);
	
	if (mid != 0) {
		printf ("  Machine: ID = %x -> %s\n", mid, getMachineName(mid));

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


Reply to: