linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Brownell <david-b@pacbell.net>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: davinci-linux-open-source@linux.davincidsp.com,
	Felipe Balbi <felipebalbi@users.sourceforge.net>,
	linux-input@vger.kernel.org
Subject: Re: [patch 2.6.28-rc6-davinci1 5/6] dm355evm input driver
Date: Wed, 14 Jan 2009 11:38:41 -0800	[thread overview]
Message-ID: <200901141138.41623.david-b@pacbell.net> (raw)
In-Reply-To: <20090113213534.ZZRA012@mailhub.coreip.homeip.net>

On Tuesday 13 January 2009, Dmitry Torokhov wrote:
> > > > +		/* Report press + release ... we can't tell if
> > > > +		 * this is an autorepeat, and we need to guess
> > > > +		 * about the release.
> > > > +		 */
> > > > +		input_report_key(keys->input, keycode, 1);
> > > 
> > > input_sync() is also needed here.
> > > 
> > > > +		input_report_key(keys->input, keycode, 0);
> > > > +	}
> > > > +	input_sync(keys->input);
> > 
> > If so, then the existing input_sync() needs to move up
> > a few lines too ... I had thought that the "sync" was
> > like with a filesystem, where lots of events could be
> > batched, but evidently not.
> > 
> 
> It is and they can. The idea is that userspace accumulates input events
> until it gets the sync event which signals that as full as possible
> hardware state was transmitted. The problem with keys is that if
> userspace really does accumulate events the 2 down/up in succession will
> cancel each other. There are really 2 separate states - button pressed
> and button released which should be accompanied with its own sync. But
> if you were reposting several buttons at once they could all "share" the
> same sync event. Does it make any sense to you?

Yes.  But now I seem to observe a LOT more events.  I suppose that's
partly due to the fuzzy semantics of these events:  they don't encode
"down" or "up".


> So you will be sending an update, right?

Appended is a patchlet addressing your feedback.  What I'll do is
submit this to the DaVinci tree, and send you an all-in-one patch.

- Dave


======= SNIP!
From: David Brownell <dbrownell@users.sourceforge.net>

Address feedback from Dmitry:
 - input_sync() per event
 - maintain dev->keybit when remapping keys
 - since we handle remapping, keycodemax and keycodesize aren't used
 - on probe error, don't input_free_device() unless it registered

Also:
 - avoid reporting excess events
 - more bad-parameter paranoia in the remapping code

The excess event issue is basically that we don't have a way to
distinguish "button press" events from "button release" ones or
autorepeat events, so we should try being a bit smarter about
synthesizing them.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
 drivers/input/keyboard/dm355evm_keys.c |   49 ++++++++++++++++++++++++-------
 1 file changed, 39 insertions(+), 10 deletions(-)

--- a/drivers/input/keyboard/dm355evm_keys.c
+++ b/drivers/input/keyboard/dm355evm_keys.c
@@ -28,6 +28,8 @@
  * using a work_struct.  The IRQ is active low, but we use it through
  * the GPIO controller so we can trigger on falling edges.
  *
+ * Note that physically there can only be one of these devices.
+ *
  * This driver was tested with firmware revision A4.
  */
 struct dm355evm_keys {
@@ -120,6 +122,8 @@ static void dm355evm_keys_work(struct wo
 	 * Reading INPUT_LOW decrements the count.
 	 */
 	for (;;) {
+		static u16	last_event;
+
 		u16		event;
 		int		keycode;
 		int		i;
@@ -142,6 +146,23 @@ static void dm355evm_keys_work(struct wo
 		if (event == 0xdead)
 			break;
 
+		/* Press and release a button:  two events, same code.
+		 * Press and hold (autorepeat), then release: N events
+		 * (N > 2), same code.  For RC5 buttons the toggle bits
+		 * distinguish (for example) "1-autorepeat" from "1 1";
+		 * but PCB buttons don't support that bit.
+		 *
+		 * So we must synthesize release events.  We do that by
+		 * mapping events to a press/release event pair; then
+		 * to avoid adding extra events, skip the second event
+		 * of each pair.
+		 */
+		if (event == last_event) {
+			last_event = 0;
+			continue;
+		}
+		last_event = event;
+
 		/* ignore the RC5 toggle bit */
 		event &= ~0x0800;
 
@@ -157,28 +178,38 @@ static void dm355evm_keys_work(struct wo
 			"input event 0x%04x--> keycode %d\n",
 			event, keycode);
 
-		/* Report press + release ... we can't tell if
-		 * this is an autorepeat, and we need to guess
-		 * about the release.
-		 */
+		/* report press + release */
 		input_report_key(keys->input, keycode, 1);
+		input_sync(keys->input);
 		input_report_key(keys->input, keycode, 0);
+		input_sync(keys->input);
 	}
-	input_sync(keys->input);
 }
 
 static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode)
 {
-	if (index >= ARRAY_SIZE(dm355evm_keys))
+	u16		old_keycode;
+	unsigned	i;
+
+	if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
 		return -EINVAL;
 
+	old_keycode = dm355evm_keys[index].keycode;
 	dm355evm_keys[index].keycode = keycode;
+	set_bit(keycode, dev->keybit);
+
+	for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
+		if (dm355evm_keys[index].keycode == old_keycode)
+			goto done;
+	}
+	clear_bit(old_keycode, dev->keybit);
+done:
 	return 0;
 }
 
 static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode)
 {
-	if (index >= ARRAY_SIZE(dm355evm_keys))
+	if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
 		return -EINVAL;
 
 	return dm355evm_keys[index].keycode;
@@ -219,8 +250,6 @@ static int __devinit dm355evm_keys_probe
 	for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++)
 		set_bit(dm355evm_keys[i].keycode, input->keybit);
 
-	input->keycodemax = ARRAY_SIZE(dm355evm_keys);
-	input->keycodesize = sizeof(dm355evm_keys[0]);
 	input->keycode = dm355evm_keys;
 	input->setkeycode = dm355evm_setkeycode;
 	input->getkeycode = dm355evm_getkeycode;
@@ -237,7 +266,7 @@ static int __devinit dm355evm_keys_probe
 	/* register */
 	status = input_register_device(input);
 	if (status < 0)
-		goto fail1;
+		goto fail0;
 
 	/* start reporting events */
 	status = request_irq(keys->irq, dm355evm_keys_irq,

      reply	other threads:[~2009-01-14 19:38 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-07 19:59 [patch 2.6.28-rc6-davinci1 5/6] dm355evm input driver David Brownell
2008-12-07 20:21 ` Felipe Balbi
2008-12-07 20:28   ` David Brownell
2008-12-07 20:34     ` Felipe Balbi
2008-12-08 21:41     ` Felipe Balbi
2008-12-08 22:19       ` David Brownell
2008-12-11  4:08 ` David Brownell
2009-01-13  6:13 ` Dmitry Torokhov
2009-01-13  9:42   ` David Brownell
2009-01-14  5:42     ` Dmitry Torokhov
2009-01-14 19:38       ` David Brownell [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200901141138.41623.david-b@pacbell.net \
    --to=david-b@pacbell.net \
    --cc=davinci-linux-open-source@linux.davincidsp.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=felipebalbi@users.sourceforge.net \
    --cc=linux-input@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).