Having only 2 buttons is a little bit of a constraining in some instances. To provide an extra button, I've modified the I2C to send MENU_KEY when the power button is pressed and released within a second and POWER_KEY when held past 1 second. It would be nice to do the same for the other key, but I'm not certain how to accomplish that. I'd assume I need a timer.

Sean

diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 09d5cfd..cf30877 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -53,7 +53,7 @@
 
 #include "pcf50633.h"
 
-#if 1
+#if 0
 #define DEBUGP(x, args ...) printk("%s: " x, __FUNCTION__, ## args)
 #define DEBUGPC(x, args ...) printk(x, ## args)
 #else
@@ -77,6 +77,7 @@ I2C_CLIENT_INSMOD_1(pcf50633);
 #define PCF50633_FIDX_PWR_PRESSED	8
 #define PCF50633_FIDX_RTC_SECOND	9
 #define PCF50633_FIDX_USB_PRESENT	10
+#define PCF50633_FIDX_PWR_HELD		11
 
 #define PCF50633_F_CHG_ENABLED	(1 << PCF50633_FIDX_CHG_ENABLED)
 #define PCF50633_F_CHG_PRESENT	(1 << PCF50633_FIDX_CHG_PRESENT)
@@ -89,6 +90,7 @@ I2C_CLIENT_INSMOD_1(pcf50633);
 #define PCF50633_F_PWR_PRESSED	(1 << PCF50633_FIDX_PWR_PRESSED)
 #define PCF50633_F_RTC_SECOND	(1 << PCF50633_FIDX_RTC_SECOND)
 #define PCF50633_F_USB_PRESENT	(1 << PCF50633_FIDX_USB_PRESENT)
+#define PCF50633_F_PWR_HELD	(1 << PCF50633_FIDX_PWR_HELD)
 
 enum close_state {
 	CLOSE_STATE_NOT,
@@ -726,15 +728,18 @@ static void pcf50633_work(struct work_struct *work)
 	if (pcfirq[1] & PCF50633_INT2_ONKEYF) {
 		/* ONKEY falling edge (start of button press) */
 		DEBUGPC("ONKEYF ");
+		input_report_key(pcf->input_dev, KEY_MENU, 1);
 		pcf->flags |= PCF50633_F_PWR_PRESSED;
-		input_report_key(pcf->input_dev, KEY_POWER, 1);
 	}
 	if (pcfirq[1] & PCF50633_INT2_ONKEYR) {
 		/* ONKEY rising edge (end of button press) */
 		DEBUGPC("ONKEYR ");
-		pcf->flags &= ~PCF50633_F_PWR_PRESSED;
+		if (pcf->flags & PCF50633_F_PWR_HELD)
+			input_report_key(pcf->input_dev, KEY_POWER, 0);
+		else
+			input_report_key(pcf->input_dev, KEY_MENU, 0);
+		pcf->flags &= ~(PCF50633_F_PWR_PRESSED|PCF50633_F_PWR_HELD);
 		pcf->onkey_seconds = -1;
-		input_report_key(pcf->input_dev, KEY_POWER, 0);
 		/* disable SECOND interrupt in case RTC didn't
 		 * request it */
 		if (!(pcf->flags & PCF50633_F_RTC_SECOND))
@@ -800,8 +805,12 @@ static void pcf50633_work(struct work_struct *work)
 	}
 	if (pcfirq[2] & PCF50633_INT3_ONKEY1S) {
 		/* ONKEY pressed for more than 1 second */
-		pcf->onkey_seconds = 0;
 		DEBUGPC("ONKEY1S ");
+		pcf->onkey_seconds = 0;
+		if (pcf->flags & PCF50633_F_PWR_PRESSED) {
+			pcf->flags |= PCF50633_F_PWR_HELD;
+			input_report_key(pcf->input_dev, KEY_POWER, 1);
+		}
 		/* Tell PMU we are taking care of this */
 		reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN,
 				 PCF50633_OOCSHDWN_TOTRST,
@@ -1735,6 +1744,7 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind)
 	data->input_dev->cdev.dev = &new_client->dev;
 
 	data->input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
+	set_bit(KEY_MENU, data->input_dev->keybit);
 	set_bit(KEY_POWER, data->input_dev->keybit);
 	set_bit(KEY_POWER2, data->input_dev->keybit);
 	set_bit(KEY_BATTERY, data->input_dev->keybit);

Reply via email to