public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Pali Rohár" <pali.rohar@gmail.com>
To: Darren Hart <dvhart@infradead.org>
Cc: Matthew Garrett <mjg59@srcf.ucam.org>,
	platform-driver-x86@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Gabriele Mazzotta <gabriele.mzt@gmail.com>
Subject: Re: [PATCH] dell-wmi: Update code for processing WMI events
Date: Wed, 22 Oct 2014 12:51:17 +0200	[thread overview]
Message-ID: <201410221251.17977@pali> (raw)
In-Reply-To: <20141021213212.GE20951@vmdeb7>

[-- Attachment #1: Type: Text/Plain, Size: 8854 bytes --]

On Tuesday 21 October 2014 23:32:12 Darren Hart wrote:
> On Tue, Oct 21, 2014 at 12:15:24AM +0200, Pali Rohár wrote:
> > WMI buffer can contains more events. First value in buffer
> > is length of event followed by data of specified length.
> > After that is next length and next data. When length is
> > zero then there is no more events in bufffer.
> > 
> > This patch adds support for processing all events in buffer
> > (not only first) and parse more event types (not only
> > hotkey events). Because of variable length of events
> > sometimes BIOS fills more hotkeys (or other values) into
> > single WMI event. In this case this patch process also
> > these multiple hotkeys (and not only first one).
> > 
> > Some event types are just ignored because kernel is not
> > interested for them (e.g. NIC Link status, battery unplug,
> > ...).
> > 
> > This patch is based on DSDT table from Dell Latitude E6440.
> > Code should be backward compatible so will process other
> > events of old types same as before this patch.
> > 
> > This patch also fixes problem when in kernel log are written
> > messages about unknown WMI events. Now all know events are
> > parsed and those which are not interesting for kernel are
> > dropped without unknown message.
> 
> This should probably be done in a separate patch.
> 

It is not possible, because my patch rewrite code for handling 
events. Kernel does not print "unknown event" messages when it 
parse WMI event and understand specified part.

> > Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
> > Tested-by: Pali Rohár <pali.rohar@gmail.com>
> 
> Well yes, I should hope so ;-)
> 
> > ---
> > 
> >  drivers/platform/x86/dell-wmi.c |  157
> >  +++++++++++++++++++++++++++++++-------- 1 file changed,
> >  127 insertions(+), 30 deletions(-)
> > 
> > diff --git a/drivers/platform/x86/dell-wmi.c
> > b/drivers/platform/x86/dell-wmi.c index 25721bf..3d15949
> > 100644
> > --- a/drivers/platform/x86/dell-wmi.c
> > +++ b/drivers/platform/x86/dell-wmi.c
> > @@ -145,11 +145,35 @@ static const u16
> > bios_to_linux_keycode[256] __initconst = {
> > 
> >  static struct input_dev *dell_wmi_input_dev;
> > 
> > +static void dell_wmi_process_key(int reported_key)
> > +{
> > +	const struct key_entry *key;
> > +
> > +	key =
> > sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
> > +						reported_key);
> > +	if (!key) {
> > +		pr_info("Unknown key %x pressed\n", reported_key);
> > +		return;
> > +	}
> > +
> > +	pr_debug("Key %x pressed\n", reported_key);
> > +
> > +	/* Don't report brightness notifications that will also
> > come via ACPI */ +	if ((key->keycode == KEY_BRIGHTNESSUP ||
> > +	     key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video)
> > +		return;
> > +
> > +	sparse_keymap_report_entry(dell_wmi_input_dev, key, 1,
> > true); +}
> > +
> > 
> >  static void dell_wmi_notify(u32 value, void *context)
> >  {
> >  
> >  	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL
> >  	}; union acpi_object *obj;
> >  	acpi_status status;
> > 
> > +	acpi_size buffer_size;
> > +	u16 *buffer_entry, *buffer_end;
> > +	int len, i;
> > 
> >  	status = wmi_get_event_data(value, &response);
> >  	if (status != AE_OK) {
> > 
> > @@ -158,44 +182,117 @@ static void dell_wmi_notify(u32
> > value, void *context)
> > 
> >  	}
> >  	
> >  	obj = (union acpi_object *)response.pointer;
> > 
> > +	if (!obj) {
> > +		pr_info("no response\n");
> > +		return;
> > +	}
> 
> If you intend to print this, it should probably be a bit more
> informative. Is "info" the right level here? I would imagine
> either WARN if this was a bad thing, or DEBUG if this is more
> for debugging the driver.
> 

So what you (or somebody else) prefer? warn or debug?

> > -	if (obj && obj->type == ACPI_TYPE_BUFFER) {
> > -		const struct key_entry *key;
> > -		int reported_key;
> > -		u16 *buffer_entry = (u16 *)obj->buffer.pointer;
> > -		int buffer_size = obj->buffer.length/2;
> > -
> > -		if (buffer_size >= 2 && dell_new_hk_type &&
> > buffer_entry[1] != 0x10) { -			pr_info("Received 
unknown
> > WMI event (0x%x)\n",
> > -				buffer_entry[1]);
> > -			kfree(obj);
> > -			return;
> > -		}
> > +	if (obj->type != ACPI_TYPE_BUFFER) {
> > +		pr_info("bad response type %x\n", obj->type);
> > +		kfree(obj);
> > +		return;
> > +	}
> > +
> > +	pr_debug("Received WMI event (%*ph)\n",
> > +		obj->buffer.length, obj->buffer.pointer);
> > 
> > -		if (buffer_size >= 3 && (dell_new_hk_type ||
> > buffer_entry[1] == 0x0)) -			reported_key =
> > (int)buffer_entry[2];
> > +	buffer_entry = (u16 *)obj->buffer.pointer;
> > +	buffer_size = obj->buffer.length/2;
> > +
> > +	if (!dell_new_hk_type) {
> > +		if (buffer_size >= 3 && buffer_entry[1] == 0x0)
> > +			dell_wmi_process_key(buffer_entry[2]);
> > 
> >  		else if (buffer_size >= 2)
> > 
> > -			reported_key = (int)buffer_entry[1] & 0xffff;
> > -		else {
> > +			dell_wmi_process_key(buffer_entry[1]);
> 
> Why can we drop the 0xffff mask now?
> 

Because it is useless (or correct me if not!). Variable 
buffer_entry has type u16* so operation "AND 0xFFFF" on 16bit 
integer do nothing.

> > +		else
> > 
> >  			pr_info("Received unknown WMI event\n");
> > 
> > -			kfree(obj);
> > -			return;
> > +		kfree(obj);
> > +		return;
> > +	}
> > +
> > +	buffer_end = buffer_entry + buffer_size;
> > +
> > +	while (buffer_entry < buffer_end) {
> > +
> > +		len = buffer_entry[0];
> > +		if (len == 0)
> > +			break;
> > +
> > +		len++;
> > +
> 
> Why increment len here? Are you trying to avoid a "len + 1" in
> the comparisons below? If so, is using "len * 2" in the debug
> message below correct? Please clarify.
> 

in buffer_entry[0] (16 bit integer) is stored length of event (in 
16bit units) without first (length) value. And "%*ph" takes size 
in bytes (u8). So length in bytes (u8) units is 2 * length in u16 
units.

> > +		if (buffer_entry+len > buffer_end) {
> 
> See coding style documentation on operators. Please run
> patches through checkpatch.
> 

checkpatch.pl does not show any problem for these lines.

> > +			pr_info("Invalid length of WMI event\n");
> 
> info doesn't see correct here either.
> 

debug or warn?

> > +			break;
> > 
> >  		}
> > 
> > -		key =
> > sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
> > -							reported_key);
> > -		if (!key) {
> > -			pr_info("Unknown key %x pressed\n", reported_key);
> > -		} else if ((key->keycode == KEY_BRIGHTNESSUP ||
> > -			    key->keycode == KEY_BRIGHTNESSDOWN) && 
acpi_video) {
> > -			/* Don't report brightness notifications that will 
also
> > -			 * come via ACPI */
> > -			;
> > -		} else {
> > -			sparse_keymap_report_entry(dell_wmi_input_dev, 
key,
> > -						   1, true);
> > +		pr_debug("Process buffer (%*ph)\n", len*2, 
buffer_entry);
> > +
> > +		switch (buffer_entry[1]) {
> > +		case 0x00:
> > +			for (i = 2; i < len; ++i) {
> > +				switch (buffer_entry[i]) {
> > +				case 0xe043:
> > +					/* NIC Link is Up */
> > +					pr_debug("NIC Link is Up\n");
> > +					break;
> > +				case 0xe044:
> > +					/* NIC Link is Down */
> > +					pr_debug("NIC Link is Down\n");
> > +					break;
> > +				case 0xe045:
> > +					/* Unknown event but defined in DSDT */
> > +				default:
> > +					/* Unknown event */
> > +					pr_info("Unknown WMI event type 0x00: "
> > +						"0x%x\n", (int)buffer_entry[i]);
> > +					break;
> > +				}
> > +			}
> > +			break;
> > +		case 0x10:
> > +			/* Keys pressed */
> > +			for (i = 2; i < len; ++i)
> > +				dell_wmi_process_key(buffer_entry[i]);
> > +			break;
> > +		case 0x11:
> > +			for (i = 2; i < len; ++i) {
> > +				switch (buffer_entry[i]) {
> > +				case 0xfff0:
> > +					/* Battery unplugged */
> > +					pr_debug("Battery unplugged\n");
> > +					break;
> > +				case 0xfff1:
> > +					/* Battery inserted */
> > +					pr_debug("Battery inserted\n");
> > +					break;
> > +				case 0x01e1:
> > +				case 0x02ea:
> > +				case 0x02eb:
> > +				case 0x02ec:
> > +				case 0x02f6:
> > +					/* Keyboard backlight level changed */
> > +					pr_debug("Keyboard backlight level "
> > +						 "changed\n");
> > +					break;
> > +				default:
> > +					/* Unknown event */
> > +					pr_info("Unknown WMI event type 0x11: "
> > +						"0x%x\n", (int)buffer_entry[i]);
> > +					break;
> > +				}
> > +			}
> > +			break;
> > +		default:
> > +			/* Unknown event */
> > +			pr_info("Unknown WMI event type 0x%x\n",
> > +				(int)buffer_entry[1]);
> > +			break;
> > 
> >  		}
> > 
> > +
> > +		buffer_entry += len;
> > +
> > 
> >  	}
> > 
> > +
> > 
> >  	kfree(obj);
> >  
> >  }

-- 
Pali Rohár
pali.rohar@gmail.com

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

  reply	other threads:[~2014-10-22 10:51 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-20 22:15 [PATCH] dell-wmi: Update code for processing WMI events Pali Rohár
2014-10-21 21:32 ` Darren Hart
2014-10-22 10:51   ` Pali Rohár [this message]
2014-11-09 15:21     ` Pali Rohár
2014-11-11  6:02       ` Darren Hart
2014-11-11 19:21         ` [PATCH v2] " Pali Rohár
2014-11-11 20:43           ` Darren Hart

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=201410221251.17977@pali \
    --to=pali.rohar@gmail.com \
    --cc=dvhart@infradead.org \
    --cc=gabriele.mzt@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mjg59@srcf.ucam.org \
    --cc=platform-driver-x86@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