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

Re: Problem with backlit keyboard on aluminium powerbook



Am Donnerstag, 23. September 2004 10:17 schrieb Pierre Habouzit:
> there is, I pointed it to the pbbutonsd author. the fact is that it
> searches for an /dev/i2c-??? device, starting from 0, to 255 until it
> finds one that responds '4' when you open it.
>
> unfortunateley, it actually take i2c-0 ... whereas on my pb, it's i2c-4
> that is the right one... you can patch in the pbbutons src the file
> src/module_pmac.c in the function called (IIRC) find_lmu_bus there is a
> loop that starts with 0 and searches the right i2-c make it start from
> 4 and all will work (at least it does here)

Please try this patch for pbbuttonsd 0.6.5. It should solve the LMU problem 
for users of /dev/i2c-4 as well as for users of /dev/i2c-0. Pbbuttonsd now 
checks /dev/i2c-4 first. I need to know if it works also on older Powerbooks 
which uses /dev/i2c-0. Feedback is very welcome.

As a side effect this patch fix the cover open/close bug which blocked the 
Brightness control keys ;-).

 Best Regards
   Matthias



diff -Naur pbbuttonsd-0.6.5/src/input_manager.c pbbuttonsd-0.6.5-fixed/src/input_manager.c
--- pbbuttonsd-0.6.5/src/input_manager.c	Fri Jul 16 18:52:02 2004
+++ pbbuttonsd-0.6.5-fixed/src/input_manager.c	Fri Sep 24 17:25:51 2004
@@ -204,7 +204,7 @@
 		sprintf(filename, "/dev/input/event%d", n);
 		if ((fd = open(filename, O_RDONLY)) >= 0) {
 			ioctl(fd, EVIOCGBIT(0, EV_MAX), bit);
-		    if (test_bit(EV_KEY, bit) && test_bit(EV_REP, bit)) {
+			if (test_bit(EV_KEY, bit) && test_bit(EV_REP, bit)) {
 				ioctl(fd, EVIOCGID, id);
 				if (id[ID_PRODUCT] != base->evdevs[m].product ||
 					id[ID_VENDOR]  != base->evdevs[m].vendor) {
diff -Naur pbbuttonsd-0.6.5/src/module_pmac.c pbbuttonsd-0.6.5-fixed/src/module_pmac.c
--- pbbuttonsd-0.6.5/src/module_pmac.c	Wed Sep  8 22:01:41 2004
+++ pbbuttonsd-0.6.5-fixed/src/module_pmac.c	Fri Sep 24 16:40:41 2004
@@ -50,6 +50,7 @@
 	int version;     /* PMU version */
 	char *identity;  /* Identity string of this laptop */
 	struct modflags_pmac flags;
+	int flagschanged;        /* PMU flags that have changed recently */
 	int oharevolbutton;      /* level of volume button on OHARE PBs scaled to 0..100 */
 	int oharebrightbutton;   /* level of brightness button on OHARE PBs scaled to 0..15 */
 
@@ -144,8 +145,10 @@
 	base->identity = identitystring;
 	ioctl(base->fd_pmu, PMU_IOC_CAN_SLEEP, &val);
 	base->flags.sleepsupported = val == 1 ? 1 : 0; /* check if sleep is supported on this system */
-	val = pmac_update_flags ();
-	pmac_update_batteryinfo (val);
+
+	pmac_update_flags ();
+	pmac_update_batteryinfo ();
+	base->flagschanged = 0;
 
 	/* Every frame buffer driver could register a backlight controller,
 	 * but only the right one is accepted. Verification is done by checking
@@ -228,7 +231,6 @@
 pmac_secure (struct tagitem *taglist)
 {
 	struct moddata_pmac *base = &modbase_pmac;
-	int cf;
 	
 	if (base->flags.set_tpmode == 1) {
 		base->flags.set_tpmode = 0;
@@ -243,12 +245,12 @@
 			process_queue_single (CONFIGQUEUE, TAG_PREPAREFORSLEEP, 0);
 #ifdef WITH_PMUD
 			activate_sleepmode ();
-			cf = pmac_update_flags ();
+			base->flagschanged = pmac_update_flags ();
 #else
 			do {
 			    activate_sleepmode ();
-			    cf = pmac_update_flags ();
-			} while (cf != -1 && base->flags.coveropen == 0);
+			    base->flagschanged = pmac_update_flags ();
+			} while (base->flags.coveropen == 0);
 #endif
 			base->timeleft = 7200;       /* reset time value so that the */
 				/* filter approximate the real value from top. Otherwise */
@@ -257,7 +259,7 @@
 				/* thresholds quick enough. This problem occours only  */
 				/* after wakeup on battery after the battery had been */
 				/* recharged during sleep.                           */
-			pmac_update_batteryinfo (cf);
+			pmac_update_batteryinfo ();
 			process_queue_single (CONFIGQUEUE, TAG_WAKEUPFROMSLEEP, 0);
 			base->batlog_cycle = batlog_setup();
 		}
@@ -441,15 +443,16 @@
 {
 	struct moddata_pmac *base = &modbase_pmac;
 	struct tagitem args[6];
-	int val, cf;
+	int val;
 
 	taglist_init (args);
 
 	val = base->timeleft;
-	cf = pmac_update_flags ();      /* ac power and cover status */
-	pmac_update_batteryinfo (cf);
+	if (base->flagschanged == 0)     /* check if anybody else has already read the flags */
+		base->flagschanged = pmac_update_flags (); /* if not, get ac power and cover status */
+	pmac_update_batteryinfo ();
 
-	if (cf & PMU_ENV_AC_POWER) {
+	if (base->flagschanged & PMU_ENV_AC_POWER) {
 		taglist_add (args, TAG_POWERCHANGED, base->flags.ac_power);
 		if (!base->flags.ac_power)      /* running on Battery */
 			base->batlog_cycle++;   /* then increase cycle */
@@ -460,7 +463,7 @@
 	}
 
 #ifndef WITH_PMUD
-	if ((cf != -1) && (cf & PMU_ENV_LID_CLOSED))
+	if (base->flagschanged & PMU_ENV_LID_CLOSED)
 		taglist_add (args, TAG_COVERSTATUS, base->flags.coveropen);
 #endif
 	if (base->version == OHARE_PMU) {         /* PowerBook 3400, etc */
@@ -484,6 +487,7 @@
 
 	if (args[0].tag != TAG_END)
 		process_queue (CONFIGQUEUE, args);  /* distribute changes to other modules */
+	base->flagschanged = 0;
 }
 
 
@@ -544,7 +548,7 @@
  * ac_power, bat_present and charging.
  */
 void
-pmac_update_batteryinfo (int cf)
+pmac_update_batteryinfo ()
 {
 	struct moddata_pmac *base = &modbase_pmac;
 	FILE *fd;
@@ -552,26 +556,6 @@
 	int val, n, syscurrent, time_rem = 0;
 	int charge, chargemax, current, voltage, timeleft[MAX_BATTERIES];
 
-	/* use /proc/pmu/info as fallback, if PMU_GET_COVER did't work
-	 * As I know this has not happend yet and it is doubtable that
-	 * /proc/pmu/info will work correctly in this case. So this
-	 * routine may be removed in future versions.
-	 */
-	if (cf == -1) {
-		print_error(_("WARNING: Couldn't get AC plug status from hardware, use /proc/pmu/info as fallback.\n"));
-		print_error(_("         Please send a message to the author if this ever happens.\n"));
-		if ((fd = fopen ("/proc/pmu/info","r"))) {
-			while (fgets (buffer, sizeof (buffer), fd))
-				if ((token = strtok (buffer,":\n"))) {
-					if (!strncmp ("AC Power", token, 8))
-						base->flags.ac_power = atoi (strtok(0,":\n"));
-					else
-						strtok (0,":\n");
-				}
-			fclose(fd);
-		}
-	}
-
 	syscurrent = 0;
 	for (n=0; n < MAX_BATTERIES; n++) {
 		charge = chargemax = current = voltage = timeleft[n] = 0;
@@ -637,6 +621,38 @@
 	}
 }
 
+/* use /proc/pmu/info as fallback, if PMU_GET_COVER did't work
+ * As I know this has not happend yet and it is doubtable that
+ * /proc/pmu/info will work correctly in this case. So this
+ * routine may be removed in future versions.
+ */	
+int
+pmac_get_procac ()
+{
+	FILE *fd;
+	char buffer[100], *token;
+	int ac = 0;  /* return battery if anything fails */
+
+	print_error(_("WARNING: Couldn't get AC plug status from hardware, use /proc/pmu/info as fallback.\n"));
+	print_error(_("         Please send a message to the author if this ever happens.\n"));
+	if ((fd = fopen ("/proc/pmu/info","r"))) {
+		while (fgets (buffer, sizeof (buffer), fd))
+			if ((token = strtok (buffer,":\n"))) {
+				if (!strncmp ("AC Power", token, 8))
+					ac = atoi (strtok(0,":\n"));
+				else
+					strtok (0,":\n");
+			}
+		fclose(fd);
+	}
+	return ac;
+}
+
+/* This funtion gets some important flags from the PMU driver. If the
+ * driver doesn't support the ioctl or reports an error, power source
+ * will be read from /proc/pmu/info as fallback, so that power source
+ * should always be set correctly.
+ */
 int
 pmac_update_flags()
 {
@@ -654,7 +670,8 @@
 		envnew  = base->flags.ac_power ? PMU_ENV_AC_POWER : 0;
 		envnew |= base->flags.coveropen ? PMU_ENV_LID_CLOSED : 0;
 	} else
-		return -1;
+		base->flags.ac_power = pmac_get_procac();
+	
 	return (envold ^ envnew);
 }
 
@@ -968,7 +985,11 @@
 
 /* This function tries to find the I2C device that controls the keyboard
  * illumination and the ambient light sensor used in alluminum PowerBooks
- * It returns the device number on success, otherwise a negative error code
+ * It returns the device number on success, otherwise a negative error code.
+ * The loop starts with device 4 because that's the correct device on
+ * 17" alluminum PowerBooks. Device 0 could be errornous detected because
+ * the function uses only circumstantial evidence to detect the correct
+ * device.
  */
 int
 lmu_find_bus ()
@@ -979,8 +1000,8 @@
 	char i2cdevice[20], buf[4];
 	int n, fd, rc = -E_NOCHAR;
 
-	for(n=0; n < 256; n++) {
-		snprintf(i2cdevice, 19, "/dev/i2c-%d", n );
+	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 ) {
@@ -988,8 +1009,8 @@
 					rc = n;
 					break;
 				}
-			} else
-				close (fd);
+			}
+			close (fd);
 		} else if (errno == ENODEV) {
 			rc = -E_NOCHAR;
 			break;
diff -Naur pbbuttonsd-0.6.5/src/module_pmac.h pbbuttonsd-0.6.5-fixed/src/module_pmac.h
--- pbbuttonsd-0.6.5/src/module_pmac.h	Fri Aug 27 08:49:31 2004
+++ pbbuttonsd-0.6.5-fixed/src/module_pmac.h	Thu Sep 23 16:18:26 2004
@@ -86,7 +86,8 @@
 void pmac_pmu_handler (int fd);
 void pmac_timer (struct tagitem *taglist);
 
-void pmac_update_batteryinfo (int cf);
+void pmac_update_batteryinfo ();
+int pmac_get_procac ();
 int pmac_update_flags ();
 void activate_sleepmode ();
 int pmac_get_lcdbacklight();

Reply to: