All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Fwd: Re: A problem about acer-wmi]
@ 2011-08-11  6:58 Joey Lee
  2011-08-11  7:45 ` AceLan Kao
  0 siblings, 1 reply; 16+ messages in thread
From: Joey Lee @ 2011-08-11  6:58 UTC (permalink / raw)
  To: acelan; +Cc: platform-driver-x86

於 四,2011-08-11 於 03:30 +0000,joeyli(Joey Lee) 提到:
> 於 四,2011-08-11 於 10:48 +0800,AceLan Kao 提到:
> > Dear Joey,
> > 
> > This is the dmesg log.
> > [ 9010.944053] acer_wmi: Acer Laptop ACPI-WMI Extras
> > [ 9010.944071] acer_wmi: Function bitmap for Communication Button: 0x1

Per this log, the 0x1 means your machine have wifi hardware module and
BIOS detected it then write information to SMBIOS area.

> > [ 9010.944075] acer_wmi: Brightness must be controlled by generic video driver
> > [ 9010.944996] input: Acer WMI hotkeys as /devices/virtual/input/input21
> > [ 9010.947095] acer_wmi: Set Device Status failed: 0xe2 - 0x0
> > 

But, 
here have problem when acer-wmi driver try to set the state by
WMID_GUID3 method, the wmi function response 0xe2.

> > And after adding my quirk, the set device status still failed, but
> > except that, everything works well.
> > 
> 
> So, you machine have wifi hardware module or not?
> 
> > The "failed" comes from acer_rfkill_init(), it'll call
> > acer_rfkill_register() with ACER_CAP_WIRELESS parameter without
> > checking the capability.
> > I don't know why only wifi doesn't check the capability and call
> > acer_rfkill_register() directly, but it doesn't hurt the system.
> > 
> > ===
> > static int acer_rfkill_init(struct device *dev)
> > {
> >         wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
> >                 "acer-wireless", ACER_CAP_WIRELESS);
> >         if (IS_ERR(wireless_rfkill))
> >                 return PTR_ERR(wireless_rfkill);
> > ===
> > 
> > Best regards,
> > AceLan Kao.
> > 
> 
> I checked the history, looks like it's just a original design in old
> patch.
> 
> Yes, you are right, add ACER_CAP_WIRELESS check is better. I am doing
> generate a patch to add ACER_CAP_WIRELESS check.
> Will attached patch on mail.
> 
> 
> Thank's
> Joey Lee
> 

Please let me know does there have any wifi module in your machine when
you test? 
If yes, then you need contact with BIOS team for why the WMID_GUID3
method response 0xe2 when set device state, because this function works
find on my TravelMate 8572 machine.

On the other hand,
The following is patch to check the ACER_CAP_WIRELESS before generate
wireless rfkill.


Thank's
Joey Lee

From 18c20f2b40bc64ec72b52ae2e4d994237173f982 Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@suse.com>
Date: Thu, 11 Aug 2011 12:49:53 +0800
Subject: [PATCH] acer-wmi: check wireless capability flag before register rfkill

There will be better to check the wireless capability flag
(ACER_CAP_WIRELESS) before register wireless rfkill because maybe
the machine doesn't have wifi module or the module removed by user.

Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
---
 drivers/platform/x86/acer-wmi.c |   64 +++++++++++++++++++++++++-------------
 1 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 712a505..b4078c4 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1289,12 +1289,13 @@ static void acer_rfkill_update(struct work_struct *ignored)
 	u32 state;
 	acpi_status status;
 
-	status = get_u32(&state, ACER_CAP_WIRELESS);
-	if (ACPI_SUCCESS(status)) {
-		if (quirks->wireless == 3) {
-			rfkill_set_hw_state(wireless_rfkill, !state);
-		} else {
-			rfkill_set_sw_state(wireless_rfkill, !state);
+	if (has_cap(ACER_CAP_WIRELESS)) {
+		status = get_u32(&state, ACER_CAP_WIRELESS);
+		if (ACPI_SUCCESS(status)) {
+			if (quirks->wireless == 3)
+				rfkill_set_hw_state(wireless_rfkill, !state);
+			else
+				rfkill_set_sw_state(wireless_rfkill, !state);
 		}
 	}
 
@@ -1362,19 +1363,24 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
 
 static int acer_rfkill_init(struct device *dev)
 {
-	wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
-		"acer-wireless", ACER_CAP_WIRELESS);
-	if (IS_ERR(wireless_rfkill))
-		return PTR_ERR(wireless_rfkill);
+	int err;
+
+	if (has_cap(ACER_CAP_WIRELESS)) {
+		wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
+			"acer-wireless", ACER_CAP_WIRELESS);
+		if (IS_ERR(wireless_rfkill)) {
+			err = PTR_ERR(wireless_rfkill);
+			goto error_wireless;
+		}
+	}
 
 	if (has_cap(ACER_CAP_BLUETOOTH)) {
 		bluetooth_rfkill = acer_rfkill_register(dev,
 			RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
 			ACER_CAP_BLUETOOTH);
 		if (IS_ERR(bluetooth_rfkill)) {
-			rfkill_unregister(wireless_rfkill);
-			rfkill_destroy(wireless_rfkill);
-			return PTR_ERR(bluetooth_rfkill);
+			err = PTR_ERR(bluetooth_rfkill);
+			goto error_bluetooth;
 		}
 	}
 
@@ -1383,30 +1389,44 @@ static int acer_rfkill_init(struct device *dev)
 			RFKILL_TYPE_WWAN, "acer-threeg",
 			ACER_CAP_THREEG);
 		if (IS_ERR(threeg_rfkill)) {
-			rfkill_unregister(wireless_rfkill);
-			rfkill_destroy(wireless_rfkill);
-			rfkill_unregister(bluetooth_rfkill);
-			rfkill_destroy(bluetooth_rfkill);
-			return PTR_ERR(threeg_rfkill);
+			err = PTR_ERR(threeg_rfkill);
+			goto error_threeg;
 		}
 	}
 
 	rfkill_inited = true;
 
-	if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
+	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
 		schedule_delayed_work(&acer_rfkill_work,
 			round_jiffies_relative(HZ));
 
 	return 0;
+
+error_threeg:
+	if (has_cap(ACER_CAP_BLUETOOTH)) {
+		rfkill_unregister(bluetooth_rfkill);
+		rfkill_destroy(bluetooth_rfkill);
+	}
+error_bluetooth:
+	if (has_cap(ACER_CAP_WIRELESS)) {
+		rfkill_unregister(wireless_rfkill);
+		rfkill_destroy(wireless_rfkill);
+	}
+error_wireless:
+	return err;
 }
 
 static void acer_rfkill_exit(void)
 {
-	if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+	if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
+	    has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
 		cancel_delayed_work_sync(&acer_rfkill_work);
 
-	rfkill_unregister(wireless_rfkill);
-	rfkill_destroy(wireless_rfkill);
+	if (has_cap(ACER_CAP_WIRELESS)) {
+		rfkill_unregister(wireless_rfkill);
+		rfkill_destroy(wireless_rfkill);
+	}
 
 	if (has_cap(ACER_CAP_BLUETOOTH)) {
 		rfkill_unregister(bluetooth_rfkill);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread
* Re: [Fwd: Re: A problem about acer-wmi]
@ 2011-08-11  3:30 Joey Lee
  0 siblings, 0 replies; 16+ messages in thread
From: Joey Lee @ 2011-08-11  3:30 UTC (permalink / raw)
  To: acelan; +Cc: Joey Lee, platform-driver-x86

於 四,2011-08-11 於 10:48 +0800,AceLan Kao 提到:
> Dear Joey,
> 
> This is the dmesg log.
> [ 9010.944053] acer_wmi: Acer Laptop ACPI-WMI Extras
> [ 9010.944071] acer_wmi: Function bitmap for Communication Button: 0x1
> [ 9010.944075] acer_wmi: Brightness must be controlled by generic video driver
> [ 9010.944996] input: Acer WMI hotkeys as /devices/virtual/input/input21
> [ 9010.947095] acer_wmi: Set Device Status failed: 0xe2 - 0x0
> 
> And after adding my quirk, the set device status still failed, but
> except that, everything works well.
> 

So, you machine have wifi hardware module or not?

> The "failed" comes from acer_rfkill_init(), it'll call
> acer_rfkill_register() with ACER_CAP_WIRELESS parameter without
> checking the capability.
> I don't know why only wifi doesn't check the capability and call
> acer_rfkill_register() directly, but it doesn't hurt the system.
> 
> ===
> static int acer_rfkill_init(struct device *dev)
> {
>         wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
>                 "acer-wireless", ACER_CAP_WIRELESS);
>         if (IS_ERR(wireless_rfkill))
>                 return PTR_ERR(wireless_rfkill);
> ===
> 
> Best regards,
> AceLan Kao.
> 

I checked the history, looks like it's just a original design in old
patch.

Yes, you are right, add ACER_CAP_WIRELESS check is better. I am doing
generate a patch to add ACER_CAP_WIRELESS check.
Will attached patch on mail.


Thank's
Joey Lee

> 2011/8/10 Joey Lee <jlee@novell.com>:
> > Hi AceLan,
> >
> > 於 三,2011-08-10 於 10:13 +0800,joeyli 提到:
> >> 於 二,2011-08-09 於 14:33 +0800,AceLan Kao 提到:
> >> > Dear Joey,
> >> >
> >> > The current project we have right now have to follow the Acer WMI to
> >> > handle the key events, that means no EC key event.
> >> > And we have 3 keys that are not working now, they are touchpad
> > toggle,
> >> > brightness up, and brightness down.
> >> > The touchpad toggle function is a Hotkey Break Event(function number
> >> > 0x2), and brightness key events are Brightness Change Event(function
> >> > number 0x4). But now acer-wmi driver only handles General Hotkey
> >> > Event(function number 0x1).
> >> >
> >>
> >> Yes, current acer-wmi only capture the event function number 0x1, you
> >> can add those new function to acer_wmi_notify().
> >>
> >> > I just implemented those 3 key events, so I think maybe we don't
> > have
> >> > to create a new acer-wmi driver.
> >>
> >> Great! Welcome for you patches, I will also test it.
> >>
> >> > I'm longing for your work to clear up the acer-wmi driver, so that I
> >> > can add the new machine id and send you the patch.
> >> > Thanks.
> >> >
> >> > BTW, I'm available to help if you are too busy to do that.
> >> >
> >> > Best regards,
> >> > AceLan Kao.
> >> >
> >>
> >> I am doing the clear up, now, will send out patch (I hope today).
> >>
> >>
> >> Thank's
> >> Joey Lee
> >>
> >
> > I add a new ACER_WMID_v2 interface flag and do some clear up in acer-wmi
> > initial function and get_u32 functions.
> >
> > Please kindly test this patch:
> >
> >
> > Thank's
> > Joey Lee
> >
> > >From 28b2e2ebaa230d339d5749b581c667ed074bb7ea Mon Sep 17 00:00:00 2001
> > From: Lee, Chun-Yi <jlee@suse.com>
> > Date: Wed, 10 Aug 2011 16:36:02 +0800
> > Subject: [PATCH] acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks
> >
> > There have new acer notebooks' BIOS provide new WMID_GUID3 and
> > ACERWMID_EVENT_GUID methods.
> >
> > Some of machines still keep the old WMID_GUID1 method but more and
> > more machines were already removed old wmi methods from DSDT.
> >
> > So, this patch add a new ACER_WMID_v2 interface flag to represent
> > new acer notebooks, the following is definition:
> >
> >  + ACER_WMID:
> >        It means this machine only provides WMID_GUID1/2 methods.
> >
> >  + ACER_WMID_v2:
> >        It means this machine provide new WMID_GUID3 and WMID_EVENT_GUID
> >        methods.
> >        Some ACER_> >        but we still query/set communication device's state by new
> >        WMID_GUID3 method.
> >
> > Tested on Acer Travelmate 8572
> >
> > Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
> > ---
> >  drivers/platform/x86/acer-wmi.c |  409 ++++++++++++++++++++-------------------
> >  1 files changed, 211 insertions(+), 198 deletions(-)
> >
> > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> > index af2bb20..712a505 100644
> > --- a/drivers/platform/x86/acer-wmi.c
> > +++ b/drivers/platform/x86/acer-wmi.c
> > @@ -190,6 +190,7 @@ enum interface_flags {
> >        ACER_AMW0,
> >        ACER_AMW0_V2,
> >        ACER_WMID,
> > +       ACER_WMID_v2,
> >  };
> >
> >  #define ACER_DEFAULT_WIRELESS  0
> > @@ -868,6 +869,176 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
> >        return WMI_execute_u32(method_id, (u32)value, NULL);
> >  }
> >
> > +static acpi_status wmid3_get_device_status(u32 *value, u16 device)
> > +{
> > +       struct wmid3_gds_return_value return_value;
> > +       acpi_status status;
> > +       union acpi_object *obj;
> > +       struct wmid3_gds_input_param params = {
> > +               .function_num = 0x1,
> > +               .hotkey_number = 0x01,
> > +               .devices = device,
> > +       };
> > +       struct acpi_buffer input = {
> > +               sizeof(struct wmid3_gds_input_param),
> > +               &params
> > +       };
> > +       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> > +
> > +       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
> > +       if (ACPI_FAILURE(status))
> > +               return status;
> > +
> > +       obj = output.pointer;
> > +
> > +       if (!obj)
> > +               return AE_ERROR;
> > +       else if (obj->type != ACPI_TYPE_BUFFER) {
> > +               kfree(obj);
> > +               return AE_ERROR;
> > +       }
> > +       if (obj->buffer.length != 8) {
> > +               pr_warn("Unknown buffer length %d\n", obj->buffer.length);
> > +               kfree(obj);
> > +               return AE_ERROR;
> > +       }
> > +
> > +       return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
> > +       kfree(obj);
> > +
> > +       if (return_value.error_code || return_value.ec_return_value)
> > +               pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
> > +                       return_value.error_code,
> > +                       return_value.ec_return_value);
> > +       else
> > +               *value = !!(return_value.devices & device);
> > +
> > +       return status;
> > +}
> > +
> > +static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
> > +{
> > +       u16 device;
> > +
> > +       switch (cap) {
> > +       case ACER_CAP_WIRELESS:
> > +               device = ACER_WMID3_GDS_WIRELESS;
> > +               break;
> > +       case ACER_CAP_BLUETOOTH:
> > +               device = ACER_WMID3_GDS_BLUETOOTH;
> > +               break;
> > +       case ACER_CAP_THREEG:
> > +               device = ACER_WMID3_GDS_THREEG;
> > +               break;
> > +       default:
> > +               return AE_ERROR;
> > +       }
> > +       return wmid3_get_device_status(value, device);
> > +}
> > +
> > +static acpi_status wmid3_set_device_status(u32 value, u16 device)
> > +{
> > +       struct wmid3_gds_return_value return_value;
> > +       acpi_status status;
> > +       union acpi_object *obj;
> > +       u16 devices;
> > +       struct wmid3_gds_input_param params = {
> > +               .function_num = 0x1,
> > +               .hotkey_number = 0x01,
> > +               .devices = ACER_WMID3_GDS_WIRELESS |
> > +                               ACER_WMID3_GDS_THREEG |
> > +                               ACER_WMID3_GDS_WIMAX |
> > +                               ACER_WMID3_GDS_BLUETOOTH,
> > +       };
> > +       struct acpi_buffer input = {
> > +               sizeof(struct wmid3_gds_input_param),
> > +           > > +       struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
> > +
> > +       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
> > +       if (ACPI_FAILURE(status))
> > +               return status;
> > +
> > +       obj = output.pointer;
> > +
> > +       if (!obj)
> > +               return AE_ERROR;
> > +       else if (obj->type != ACPI_TYPE_BUFFER) {
> > +               kfree(obj);
> > +               return AE_ERROR;
> > +       }
> > +       if (obj->buffer.length != 8) {
> > +               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
> > +               kfree(obj);
> > +               return AE_ERROR;
> > +       }
> > +
> > +       return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
> > +       kfree(obj);
> > +
> > +       if (return_value.error_code || return_value.ec_return_value) {
> > +               pr_warning("Get Current Device Status failed: "
> > +                       "0x%x - 0x%x\n", return_value.error_code,
> > +                       return_value.ec_return_value);
> > +               return status;
> > +       }
> > +
> > +       devices = return_value.devices;
> > +       params.function_num = 0x2;
> > +       params.hotkey_number = 0x01;
> > +       params.devices = (value) ? (devices | device) : (devices & ~device);
> > +
> > +       status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
> > +       if (ACPI_FAILURE(status))
> > +               return status;
> > +
> > +       obj = output2.pointer;
> > +
> > +       if (!obj)
> > +               return AE_ERROR;
> > +       else if (obj->type != ACPI_TYPE_BUFFER) {
> > +               kfree(obj);
> > +               return AE_ERROR;
> > +       }
> > +       if (obj->buffer.length != 4) {
> > +               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
> > +               kfree(obj);
> > +               return AE_ERROR;
> > +       }
> > +
> > +       return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
> > +       kfree(obj);
> > +
> > +       if (return_value.error_code || return_value.ec_return_value)
> > +               pr_warning("Set Device Status failed: "
> > +                       "0x%x - 0x%x\n", return_value.error_code,
> > +                       return_value.ec_return_value);
> > +
> > +       return status;
> > +}
> > +
> > +static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
> > +{
> > +       u16 device;
> > +
> > +       switch (cap) {
> > +       case ACER_CAP_WIRELESS:
> > +               device = ACER_WMID3_GDS_WIRELESS;
> > +               break;
> > +       case ACER_CAP_BLUETOOTH:
> > +               device = ACER_WMID3_GDS_BLUETOOTH;
> > +               break;
> > +       case ACER_CAP_THREEG:
> > +               device = ACER_WMID3_GDS_THREEG;
> > +               break;
> > +       default:
> > +               return AE_ERROR;
> > +       }
> > +       return wmid3_set_device_status(value, device);
> > +}
> > +
> >  static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
> >  {
> >        struct hotkey_function_type_aa *type_aa;
> > @@ -913,17 +1084,11 @@ static acpi_status WMID_set_capabilities(void)
> >                return AE_ERROR;
> >        }
> >
> > -       dmi_walk(type_aa_dmi_decode, NULL);
> > -       if (!has_type_aa) {
> > -               interface->capability |= ACER_CAP_WIRELESS;
> > -               if (devices & 0x40)
> > -                       interface->capability |= ACER_CAP_THREEG;
> > -               if (devices & 0x10)
> > -                       interface->capability |= ACER_CAP_BLUETOOTH;
> > -       }
> > -
> > -       /* WMID always provides brightness methods */
> > -       interface->capability |= ACER_CAP_BRIGHTNESS;
> > +       interface->capability |= ACER_CAP_WIRELESS;
> > +       if (devices & 0x40)
> > +               interface->capability |= ACER_CAP_THREEG;
> > +       if (devices & 0x10)
> > +               interface->capability |= A> > @@ -936,6 +1101,10 @@ static struct wmi_interface wmid_interface = {
> >        .type = ACER_WMID,
> >  };
> >
> > +static struct wmi_interface wmid_v2_interface = {
> > +       .type = ACER_WMID_v2,
> > +};
> > +
> >  /*
> >  * Generic Device (interface-independent)
> >  */
> > @@ -956,6 +1125,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
> >        case ACER_WMID:
> >                status = WMID_get_u32(value, cap, interface);
> >                break;
> > +       case ACER_WMID_v2:
> > +               if (cap & (ACER_CAP_WIRELESS |
> > +                          ACER_CAP_BLUETOOTH |
> > +                          ACER_CAP_THREEG))
> > +                       status = wmid_v2_get_u32(value, cap);
> > +               else if (wmi_has_guid(WMID_GUID2))
> > +                       status = WMID_get_u32(value, cap, interface);
> > +               break;
> >        }
> >
> >        return status;
> > @@ -989,6 +1166,13 @@ static acpi_status set_u32(u32 value, u32 cap)
> >                        }
> >                case ACER_WMID:
> >                        return WMID_set_u32(value, cap, interface);
> > +               case ACER_WMID_v2:
> > +                       if (cap & (ACER_CAP_WIRELESS |
> > +                                  ACER_CAP_BLUETOOTH |
> > +                                  ACER_CAP_THREEG))
> > +                               return wmid_v2_set_u32(value, cap);
> > +                       else if (wmi_has_guid(WMID_GUID2))
> > +                               return WMID_set_u32(value, cap, interface);
> >                default:
> >                        return AE_BAD_PARAMETER;
> >                }
> > @@ -1095,186 +1279,6 @@ static void acer_backlight_exit(void)
> >        backlight_device_unregister(acer_backlight_device);
> >  }
> >
> > -static acpi_status wmid3_get_device_status(u32 *value, u16 device)
> > -{
> > -       struct wmid3_gds_return_value return_value;
> > -       acpi_status status;
> > -       union acpi_object *obj;
> > -       struct wmid3_gds_input_param params = {
> > -               .function_num = 0x1,
> > -               .hotkey_number = 0x01,
> > -               .devices = device,
> > -       };
> > -       struct acpi_buffer input = {
> > -               sizeof(struct wmid3_gds_input_param),
> > -               &params
> > -       };
> > -       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> > -
> > -       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
> > -       if (ACPI_FAILURE(status))
> > -               return status;
> > -
> > -       obj = output.pointer;
> > -
> > -       if (!obj)
> > -               return AE_ERROR;
> > -       else if (obj->type != ACPI_TYPE_BUFFER) {
> > -               kfree(obj);
> > -               return AE_ERROR;
> > -       }
> > -       if (obj->buffer.length != 8) {
> > -               pr_warn("Unknown buffer length %d\n", obj->buffer.length);
> > -               kfree(obj);
> > -               return AE_ERROR;
> > -       }
> > -
> > -       return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
> > -       kfree(obj);
> > -
> > -       if (return_value.error_code || return_value.ec_return_value)
> > -               pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
> > -                       return_value.error_code,
> > -                       return_value.ec_return_value);
> > -       else
> > -               *value = !!(return_value.devices & device);
> > -
> > -       return status;
> > -}
> > -
> > -static acpi_status get_device_status(u32 *value, u32 cap)
> > -{
> > -       if (wmi_has_guid(WMID_GUID3)) {
> > -               u16 device;
> > -
> > -               switch (cap) {
> > -               case ACER_CAP_WIRELESS:
> > -                       device = ACER_WMID3_GDS_WIRELESS;
> > -                       break;
> > -               case ACER_CAP_BLUETOOTH:
> > -                       device = ACER_WMID3_GDS_BLUETOOTH;
> > -                       break;
> > -> > -                       break;
> > -               default:
> > -                       return AE_ERROR;
> > -               }
> > -               return wmid3_get_device_status(value, device);
> > -
> > -       } else {
> > -               return get_u32(value, cap);
> > -       }
> > -}
> > -
> > -static acpi_status wmid3_set_device_status(u32 value, u16 device)
> > -{
> > -       struct wmid3_gds_return_value return_value;
> > -       acpi_status status;
> > -       union acpi_object *obj;
> > -       u16 devices;
> > -       struct wmid3_gds_input_param params = {
> > -               .function_num = 0x1,
> > -               .hotkey_number = 0x01,
> > -               .devices = ACER_WMID3_GDS_WIRELESS |
> > -                               ACER_WMID3_GDS_THREEG |
> > -                               ACER_WMID3_GDS_WIMAX |
> > -                               ACER_WMID3_GDS_BLUETOOTH,
> > -       };
> > -       struct acpi_buffer input = {
> > -               sizeof(struct wmid3_gds_input_param),
> > -               &params
> > -       };
> > -       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> > -       struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
> > -
> > -       status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
> > -       if (ACPI_FAILURE(status))
> > -               return status;
> > -
> > -       obj = output.pointer;
> > -
> > -       if (!obj)
> > -               return AE_ERROR;
> > -       else if (obj->type != ACPI_TYPE_BUFFER) {
> > -               kfree(obj);
> > -               return AE_ERROR;
> > -       }
> > -       if (obj->buffer.length != 8) {
> > -               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
> > -               kfree(obj);
> > -               return AE_ERROR;
> > -       }
> > -
> > -       return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
> > -       kfree(obj);
> > -
> > -       if (return_value.error_code || return_value.ec_return_value) {
> > -               pr_warning("Get Current Device Status failed: "
> > -                       "0x%x - 0x%x\n", return_value.error_code,
> > -                       return_value.ec_return_value);
> > -               return status;
> > -       }
> > -
> > -       devices = return_value.devices;
> > -       params.function_num = 0x2;
> > -       params.hotkey_number = 0x01;
> > -       params.devices = (value) ? (devices | device) : (devices & ~device);
> > -
> > -       status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
> > -       if (ACPI_FAILURE(status))
> > -               return status;
> > -
> > -       obj = output2.pointer;
> > -
> > -       if (!obj)
> > -               return AE_ERROR;
> > -       else if (obj->type != ACPI_TYPE_BUFFER) {
> > -               kfree(obj);
> > -               return AE_ERROR;
> > -       }
> > -       if (obj->buffer.length != 4) {
> > -               pr_warning("Unknown buffer length %d\n", obj->buffer.length);
> > -               kfree(obj);
> > -               return AE_ERROR;
> > -       }
> > -
> > -       return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
> > -       kfree(obj);
> > -
> > -       if (return_value.error_code || return_value.ec_return_value)
> > -               pr_warning("Set Device Status failed: "
> > -                       "0x%x - 0x%x\n", return_value.error_code,
> > -                       return_value.ec_return_value);
> > -
> > -       return status;
> > -}
> > -
> > -static acpi_status set_device_status(u32 value, u32 cap)
> > -{
> > -       if (wmi_has_guid(WMID_GUID3)) {
> > -               u16 device;
> > -
> > -               switch (cap) {
> > -               case ACER_CAP_WIRELESS:
> > -                       device = ACER_WMID3_GDS_WIRELESS;
> > -                       break;
> > -               case ACER_CAP_BLUETOOTH:
> > -                       device = ACER_WMID3_GDS_BLUETOOTH;
> > -                       break;
> > -               case ACER_CAP_THREEG:
> > -                       device = ACE> > -                       return AE_ERROR;
> > -               }
> > -               return wmid3_set_device_status(value, device);
> > -
> > -       } else {
> > -               return set_u32(value, cap);
> > -       }
> > -}
> > -
> >  /*
> >  * Rfkill devices
> >  */
> > @@ -1301,8 +1305,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
> >        }
> >
> >        if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
> > -               status = wmid3_get_device_status(&state,
> > -                               ACER_WMID3_GDS_THREEG);
> > +               status = get_u32(&state, ACER_WMID3_GDS_THREEG);
> >                if (ACPI_SUCCESS(status))
> >                        rfkill_set_sw_state(threeg_rfkill, !state);
> >        }
> > @@ -1316,7 +1319,7 @@ static int acer_rfkill_set(void *data, bool blocked)
> >        u32 cap = (unsigned long)data;
> >
> >        if (rfkill_inited) {
> > -               status = set_device_status(!blocked, cap);
> > +               status = set_u32(!blocked, cap);
> >                if (ACPI_FAILURE(status))
> >                        return -ENODEV;
> >        }
> > @@ -1343,7 +1346,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
> >        if (!rfkill_dev)
> >                return ERR_PTR(-ENOMEM);
> >
> > -       status = get_device_status(&state, cap);
> > +       status = get_u32(&state, cap);
> >
> >        err = rfkill_register(rfkill_dev);
> >        if (err) {
> > @@ -1464,6 +1467,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
> >                return sprintf(buf, "AMW0 v2\n");
> >        case ACER_WMID:
> >                return sprintf(buf, "WMID\n");
> > +       case ACER_WMID_v2:
> > +               return sprintf(buf, "WMID v2\n");
> >        default:
> >                return sprintf(buf, "Error!\n");
> >        }
> > @@ -1883,12 +1888,20 @@ static int __init acer_wmi_init(void)
> >        if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
> >                interface = &wmid_interface;
> >
> > +       if (wmi_has_guid(WMID_GUID3))
> > +               interface = &wmid_v2_interface;
> > +
> > +       if (interface)
> > +               dmi_walk(type_aa_dmi_decode, NULL);
> > +
> >        if (wmi_has_guid(WMID_GUID2) && interface) {
> > -               if (ACPI_FAILURE(WMID_set_capabilities())) {
> > +               if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
> >                        pr_err("Unable to detect available WMID devices\n");
> >                        return -ENODEV;
> >                }
> > -       } else if (!wmi_has_guid(WMID_GUID2) && interface) {
> > +               /* WMID always provides brightness methods */
> > +               interface->capability |= ACER_CAP_BRIGHTNESS;
> > +       } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
> >                pr_err("No WMID device detection method found\n");
> >                return -ENODEV;
> >        }
> > @@ -1912,7 +1925,7 @@ static int __init acer_wmi_init(void)
> >
> >        set_quirks();
> >
> > -       if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
> > +       if (acpi_video_backlight_support()) {
> >                interface->capability &= ~ACER_CAP_BRIGHTNESS;
> >                pr_info("Brightness must be controlled by "
> >                       "generic video driver\n");
> > --
> > 1.6.0.2
> >
> >
> >
> >
> 
> 
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread
* Re: [Fwd: Re: A problem about acer-wmi]
@ 2011-08-10 10:02 Joey Lee
  2011-08-11  2:48 ` AceLan Kao
  0 siblings, 1 reply; 16+ messages in thread
From: Joey Lee @ 2011-08-10 10:02 UTC (permalink / raw)
  To: acelan; +Cc: acelan.kao, joeyli.kernel, platform-driver-x86

Hi AceLan,

於 三,2011-08-10 於 10:13 +0800,joeyli 提到:
> 於 二,2011-08-09 於 14:33 +0800,AceLan Kao 提到:
> > Dear Joey,
> > 
> > The current project we have right now have to follow the Acer WMI to
> > handle the key events, that means no EC key event.
> > And we have 3 keys that are not working now, they are touchpad
toggle,
> > brightness up, and brightness down.
> > The touchpad toggle function is a Hotkey Break Event(function number
> > 0x2), and brightness key events are Brightness Change Event(function
> > number 0x4). But now acer-wmi driver only handles General Hotkey
> > Event(function number 0x1).
> > 
> 
> Yes, current acer-wmi only capture the event function number 0x1, you
> can add those new function to acer_wmi_notify().
> 
> > I just implemented those 3 key events, so I think maybe we don't
have
> > to create a new acer-wmi driver.
> 
> Great! Welcome for you patches, I will also test it.
> 
> > I'm longing for your work to clear up the acer-wmi driver, so that I
> > can add the new machine id and send you the patch.
> > Thanks.
> > 
> > BTW, I'm available to help if you are too busy to do that.
> > 
> > Best regards,
> > AceLan Kao.
> > 
> 
> I am doing the clear up, now, will send out patch (I hope today).
> 
> 
> Thank's
> Joey Lee
> 

I add a new ACER_WMID_v2 interface flag and do some clear up in acer-wmi
initial function and get_u32 functions.

Please kindly test this patch:


Thank's
Joey Lee

From 28b2e2ebaa230d339d5749b581c667ed074bb7ea Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@suse.com>
Date: Wed, 10 Aug 2011 16:36:02 +0800
Subject: [PATCH] acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks

There have new acer notebooks' BIOS provide new WMID_GUID3 and
ACERWMID_EVENT_GUID methods.

Some of machines still keep the old WMID_GUID1 method but more and
more machines were already removed old wmi methods from DSDT.

So, this patch add a new ACER_WMID_v2 interface flag to represent
new acer notebooks, the following is definition:

 + ACER_WMID:
        It means this machine only provides WMID_GUID1/2 methods.

 + ACER_WMID_v2:
        It means this machine provide new WMID_GUID3 and WMID_EVENT_GUID
        methods.
        Some ACER_WMID_v2 machines also provide old WMID_GUID1/2 methods,
        but we still query/set communication device's state by new
        WMID_GUID3 method.

Tested on Acer Travelmate 8572

Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
---
 drivers/platform/x86/acer-wmi.c |  409 ++++++++++++++++++++-------------------
 1 files changed, 211 insertions(+), 198 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index af2bb20..712a505 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -190,6 +190,7 @@ enum interface_flags {
 	ACER_AMW0,
 	ACER_AMW0_V2,
 	ACER_WMID,
+	ACER_WMID_v2,
 };
 
 #define ACER_DEFAULT_WIRELESS  0
@@ -868,6 +869,176 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
 	return WMI_execute_u32(method_id, (u32)value, NULL);
 }
 
+static acpi_status wmid3_get_device_status(u32 *value, u16 device)
+{
+	struct wmid3_gds_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	struct wmid3_gds_input_param params = {
+		.function_num = 0x1,
+		.hotkey_number = 0x01,
+		.devices = device,
+	};
+	struct acpi_buffer input = {
+		sizeof(struct wmid3_gds_input_param),
+		&params
+	};
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output.pointer;
+
+	if (!obj)
+		return AE_ERROR;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return AE_ERROR;
+	}
+	if (obj->buffer.length != 8) {
+		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
+		kfree(obj);
+		return AE_ERROR;
+	}
+
+	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	if (return_value.error_code || return_value.ec_return_value)
+		pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
+			return_value.error_code,
+			return_value.ec_return_value);
+	else
+		*value = !!(return_value.devices & device);
+
+	return status;
+}
+
+static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
+{
+	u16 device;
+
+	switch (cap) {
+	case ACER_CAP_WIRELESS:
+		device = ACER_WMID3_GDS_WIRELESS;
+		break;
+	case ACER_CAP_BLUETOOTH:
+		device = ACER_WMID3_GDS_BLUETOOTH;
+		break;
+	case ACER_CAP_THREEG:
+		device = ACER_WMID3_GDS_THREEG;
+		break;
+	default:
+		return AE_ERROR;
+	}
+	return wmid3_get_device_status(value, device);
+}
+
+static acpi_status wmid3_set_device_status(u32 value, u16 device)
+{
+	struct wmid3_gds_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	u16 devices;
+	struct wmid3_gds_input_param params = {
+		.function_num = 0x1,
+		.hotkey_number = 0x01,
+		.devices = ACER_WMID3_GDS_WIRELESS |
+				ACER_WMID3_GDS_THREEG |
+				ACER_WMID3_GDS_WIMAX |
+				ACER_WMID3_GDS_BLUETOOTH,
+	};
+	struct acpi_buffer input = {
+		sizeof(struct wmid3_gds_input_param),
+		&params
+	};
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output.pointer;
+
+	if (!obj)
+		return AE_ERROR;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return AE_ERROR;
+	}
+	if (obj->buffer.length != 8) {
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+		kfree(obj);
+		return AE_ERROR;
+	}
+
+	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	if (return_value.error_code || return_value.ec_return_value) {
+		pr_warning("Get Current Device Status failed: "
+			"0x%x - 0x%x\n", return_value.error_code,
+			return_value.ec_return_value);
+		return status;
+	}
+
+	devices = return_value.devices;
+	params.function_num = 0x2;
+	params.hotkey_number = 0x01;
+	params.devices = (value) ? (devices | device) : (devices & ~device);
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output2.pointer;
+
+	if (!obj)
+		return AE_ERROR;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return AE_ERROR;
+	}
+	if (obj->buffer.length != 4) {
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+		kfree(obj);
+		return AE_ERROR;
+	}
+
+	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	if (return_value.error_code || return_value.ec_return_value)
+		pr_warning("Set Device Status failed: "
+			"0x%x - 0x%x\n", return_value.error_code,
+			return_value.ec_return_value);
+
+	return status;
+}
+
+static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
+{
+	u16 device;
+
+	switch (cap) {
+	case ACER_CAP_WIRELESS:
+		device = ACER_WMID3_GDS_WIRELESS;
+		break;
+	case ACER_CAP_BLUETOOTH:
+		device = ACER_WMID3_GDS_BLUETOOTH;
+		break;
+	case ACER_CAP_THREEG:
+		device = ACER_WMID3_GDS_THREEG;
+		break;
+	default:
+		return AE_ERROR;
+	}
+	return wmid3_set_device_status(value, device);
+}
+
 static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
 {
 	struct hotkey_function_type_aa *type_aa;
@@ -913,17 +1084,11 @@ static acpi_status WMID_set_capabilities(void)
 		return AE_ERROR;
 	}
 
-	dmi_walk(type_aa_dmi_decode, NULL);
-	if (!has_type_aa) {
-		interface->capability |= ACER_CAP_WIRELESS;
-		if (devices & 0x40)
-			interface->capability |= ACER_CAP_THREEG;
-		if (devices & 0x10)
-			interface->capability |= ACER_CAP_BLUETOOTH;
-	}
-
-	/* WMID always provides brightness methods */
-	interface->capability |= ACER_CAP_BRIGHTNESS;
+	interface->capability |= ACER_CAP_WIRELESS;
+	if (devices & 0x40)
+		interface->capability |= ACER_CAP_THREEG;
+	if (devices & 0x10)
+		interface->capability |= ACER_CAP_BLUETOOTH;
 
 	if (!(devices & 0x20))
 		max_brightness = 0x9;
@@ -936,6 +1101,10 @@ static struct wmi_interface wmid_interface = {
 	.type = ACER_WMID,
 };
 
+static struct wmi_interface wmid_v2_interface = {
+	.type = ACER_WMID_v2,
+};
+
 /*
  * Generic Device (interface-independent)
  */
@@ -956,6 +1125,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
 	case ACER_WMID:
 		status = WMID_get_u32(value, cap, interface);
 		break;
+	case ACER_WMID_v2:
+		if (cap & (ACER_CAP_WIRELESS |
+			   ACER_CAP_BLUETOOTH |
+			   ACER_CAP_THREEG))
+			status = wmid_v2_get_u32(value, cap);
+		else if (wmi_has_guid(WMID_GUID2))
+			status = WMID_get_u32(value, cap, interface);
+		break;
 	}
 
 	return status;
@@ -989,6 +1166,13 @@ static acpi_status set_u32(u32 value, u32 cap)
 			}
 		case ACER_WMID:
 			return WMID_set_u32(value, cap, interface);
+		case ACER_WMID_v2:
+			if (cap & (ACER_CAP_WIRELESS |
+				   ACER_CAP_BLUETOOTH |
+				   ACER_CAP_THREEG))
+				return wmid_v2_set_u32(value, cap);
+			else if (wmi_has_guid(WMID_GUID2))
+				return WMID_set_u32(value, cap, interface);
 		default:
 			return AE_BAD_PARAMETER;
 		}
@@ -1095,186 +1279,6 @@ static void acer_backlight_exit(void)
 	backlight_device_unregister(acer_backlight_device);
 }
 
-static acpi_status wmid3_get_device_status(u32 *value, u16 device)
-{
-	struct wmid3_gds_return_value return_value;
-	acpi_status status;
-	union acpi_object *obj;
-	struct wmid3_gds_input_param params = {
-		.function_num = 0x1,
-		.hotkey_number = 0x01,
-		.devices = device,
-	};
-	struct acpi_buffer input = {
-		sizeof(struct wmid3_gds_input_param),
-		&params
-	};
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-
-	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = output.pointer;
-
-	if (!obj)
-		return AE_ERROR;
-	else if (obj->type != ACPI_TYPE_BUFFER) {
-		kfree(obj);
-		return AE_ERROR;
-	}
-	if (obj->buffer.length != 8) {
-		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
-		kfree(obj);
-		return AE_ERROR;
-	}
-
-	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
-	kfree(obj);
-
-	if (return_value.error_code || return_value.ec_return_value)
-		pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
-			return_value.error_code,
-			return_value.ec_return_value);
-	else
-		*value = !!(return_value.devices & device);
-
-	return status;
-}
-
-static acpi_status get_device_status(u32 *value, u32 cap)
-{
-	if (wmi_has_guid(WMID_GUID3)) {
-		u16 device;
-
-		switch (cap) {
-		case ACER_CAP_WIRELESS:
-			device = ACER_WMID3_GDS_WIRELESS;
-			break;
-		case ACER_CAP_BLUETOOTH:
-			device = ACER_WMID3_GDS_BLUETOOTH;
-			break;
-		case ACER_CAP_THREEG:
-			device = ACER_WMID3_GDS_THREEG;
-			break;
-		default:
-			return AE_ERROR;
-		}
-		return wmid3_get_device_status(value, device);
-
-	} else {
-		return get_u32(value, cap);
-	}
-}
-
-static acpi_status wmid3_set_device_status(u32 value, u16 device)
-{
-	struct wmid3_gds_return_value return_value;
-	acpi_status status;
-	union acpi_object *obj;
-	u16 devices;
-	struct wmid3_gds_input_param params = {
-		.function_num = 0x1,
-		.hotkey_number = 0x01,
-		.devices = ACER_WMID3_GDS_WIRELESS |
-				ACER_WMID3_GDS_THREEG |
-				ACER_WMID3_GDS_WIMAX |
-				ACER_WMID3_GDS_BLUETOOTH,
-	};
-	struct acpi_buffer input = {
-		sizeof(struct wmid3_gds_input_param),
-		&params
-	};
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
-
-	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = output.pointer;
-
-	if (!obj)
-		return AE_ERROR;
-	else if (obj->type != ACPI_TYPE_BUFFER) {
-		kfree(obj);
-		return AE_ERROR;
-	}
-	if (obj->buffer.length != 8) {
-		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
-		kfree(obj);
-		return AE_ERROR;
-	}
-
-	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
-	kfree(obj);
-
-	if (return_value.error_code || return_value.ec_return_value) {
-		pr_warning("Get Current Device Status failed: "
-			"0x%x - 0x%x\n", return_value.error_code,
-			return_value.ec_return_value);
-		return status;
-	}
-
-	devices = return_value.devices;
-	params.function_num = 0x2;
-	params.hotkey_number = 0x01;
-	params.devices = (value) ? (devices | device) : (devices & ~device);
-
-	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = output2.pointer;
-
-	if (!obj)
-		return AE_ERROR;
-	else if (obj->type != ACPI_TYPE_BUFFER) {
-		kfree(obj);
-		return AE_ERROR;
-	}
-	if (obj->buffer.length != 4) {
-		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
-		kfree(obj);
-		return AE_ERROR;
-	}
-
-	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
-	kfree(obj);
-
-	if (return_value.error_code || return_value.ec_return_value)
-		pr_warning("Set Device Status failed: "
-			"0x%x - 0x%x\n", return_value.error_code,
-			return_value.ec_return_value);
-
-	return status;
-}
-
-static acpi_status set_device_status(u32 value, u32 cap)
-{
-	if (wmi_has_guid(WMID_GUID3)) {
-		u16 device;
-
-		switch (cap) {
-		case ACER_CAP_WIRELESS:
-			device = ACER_WMID3_GDS_WIRELESS;
-			break;
-		case ACER_CAP_BLUETOOTH:
-			device = ACER_WMID3_GDS_BLUETOOTH;
-			break;
-		case ACER_CAP_THREEG:
-			device = ACER_WMID3_GDS_THREEG;
-			break;
-		default:
-			return AE_ERROR;
-		}
-		return wmid3_set_device_status(value, device);
-
-	} else {
-		return set_u32(value, cap);
-	}
-}
-
 /*
  * Rfkill devices
  */
@@ -1301,8 +1305,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
 	}
 
 	if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
-		status = wmid3_get_device_status(&state,
-				ACER_WMID3_GDS_THREEG);
+		status = get_u32(&state, ACER_WMID3_GDS_THREEG);
 		if (ACPI_SUCCESS(status))
 			rfkill_set_sw_state(threeg_rfkill, !state);
 	}
@@ -1316,7 +1319,7 @@ static int acer_rfkill_set(void *data, bool blocked)
 	u32 cap = (unsigned long)data;
 
 	if (rfkill_inited) {
-		status = set_device_status(!blocked, cap);
+		status = set_u32(!blocked, cap);
 		if (ACPI_FAILURE(status))
 			return -ENODEV;
 	}
@@ -1343,7 +1346,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
 	if (!rfkill_dev)
 		return ERR_PTR(-ENOMEM);
 
-	status = get_device_status(&state, cap);
+	status = get_u32(&state, cap);
 
 	err = rfkill_register(rfkill_dev);
 	if (err) {
@@ -1464,6 +1467,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
 		return sprintf(buf, "AMW0 v2\n");
 	case ACER_WMID:
 		return sprintf(buf, "WMID\n");
+	case ACER_WMID_v2:
+		return sprintf(buf, "WMID v2\n");
 	default:
 		return sprintf(buf, "Error!\n");
 	}
@@ -1883,12 +1888,20 @@ static int __init acer_wmi_init(void)
 	if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
 		interface = &wmid_interface;
 
+	if (wmi_has_guid(WMID_GUID3))
+		interface = &wmid_v2_interface;
+
+	if (interface)
+		dmi_walk(type_aa_dmi_decode, NULL);
+
 	if (wmi_has_guid(WMID_GUID2) && interface) {
-		if (ACPI_FAILURE(WMID_set_capabilities())) {
+		if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
 			pr_err("Unable to detect available WMID devices\n");
 			return -ENODEV;
 		}
-	} else if (!wmi_has_guid(WMID_GUID2) && interface) {
+		/* WMID always provides brightness methods */
+		interface->capability |= ACER_CAP_BRIGHTNESS;
+	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
 		pr_err("No WMID device detection method found\n");
 		return -ENODEV;
 	}
@@ -1912,7 +1925,7 @@ static int __init acer_wmi_init(void)
 
 	set_quirks();
 
-	if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
+	if (acpi_video_backlight_support()) {
 		interface->capability &= ~ACER_CAP_BRIGHTNESS;
 		pr_info("Brightness must be controlled by "
 		       "generic video driver\n");
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread
* Re: [Fwd: Re: A problem about acer-wmi]
@ 2011-08-10  9:17 Joey Lee
  0 siblings, 0 replies; 16+ messages in thread
From: Joey Lee @ 2011-08-10  9:17 UTC (permalink / raw)
  To: acelan; +Cc: platform-driver-x86

Hi AceLan,

於 三,2011-08-10 於 10:13 +0800,joeyli 提到:
> 於 二,2011-08-09 於 14:33 +0800,AceLan Kao 提到:
> > Dear Joey,
> > 
> > The current project we have right now have to follow the Acer WMI to
> > handle the key events, that means no EC key event.
> > And we have 3 keys that are not working now, they are touchpad
toggle,
> > brightness up, and brightness down.
> > The touchpad toggle function is a Hotkey Break Event(function number
> > 0x2), and brightness key events are Brightness Change Event(function
> > number 0x4). But now acer-wmi driver only handles General Hotkey
> > Event(function number 0x1).
> > 
> 
> Yes, current acer-wmi only capture the event function number 0x1, you
> can add those new function to acer_wmi_notify().
> 
> > I just implemented those 3 key events, so I think maybe we don't
have
> > to create a new acer-wmi driver.
> 
> Great! Welcome for you patches, I will also test it.
> 
> > I'm longing for your work to clear up the acer-wmi driver, so that I
> > can add the new machine id and send you the patch.
> > Thanks.
> > 
> > BTW, I'm available to help if you are too busy to do that.
> > 
> > Best regards,
> > AceLan Kao.
> > 
> 
> I am doing the clear up, now, will send out patch (I hope today).
> 
> 
> Thank's
> Joey Lee
> 

I add a new ACER_WMID_v2 interface flag and do some clear up in acer-wmi
initial function and get_u32 functions.

Please kindly test this patch:


Thank's
Joey Lee


From 28b2e2ebaa230d339d5749b581c667ed074bb7ea Mon Sep 17 00:00:00 2001
From: Lee, Chun-Yi <jlee@suse.com>
Date: Wed, 10 Aug 2011 16:36:02 +0800
Subject: [PATCH] acer-wmi: add ACER_WMID_v2 interface flag to represent new notebooks

There have new acer notebooks' BIOS provide new WMID_GUID3 and
ACERWMID_EVENT_GUID methods.

Some of machines still keep the old WMID_GUID1 method but more and
more machines were already removed old wmi methods from DSDT.

So, this patch add a new ACER_WMID_v2 interface flag to represent
new acer notebooks, the following is definition:

 + ACER_WMID:
        It means this machine only provides WMID_GUID1/2 methods.

 + ACER_WMID_v2:
        It means this machine provide new WMID_GUID3 and WMID_EVENT_GUID
        methods.
        Some ACER_WMID_v2 machines also provide old WMID_GUID1/2 methods,
        but we still query/set communication device's state by new
        WMID_GUID3 method.

Tested on Acer Travelmate 8572

Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
---
 drivers/platform/x86/acer-wmi.c |  409 ++++++++++++++++++++-------------------
 1 files changed, 211 insertions(+), 198 deletions(-)

diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index af2bb20..712a505 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -190,6 +190,7 @@ enum interface_flags {
 	ACER_AMW0,
 	ACER_AMW0_V2,
 	ACER_WMID,
+	ACER_WMID_v2,
 };
 
 #define ACER_DEFAULT_WIRELESS  0
@@ -868,6 +869,176 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
 	return WMI_execute_u32(method_id, (u32)value, NULL);
 }
 
+static acpi_status wmid3_get_device_status(u32 *value, u16 device)
+{
+	struct wmid3_gds_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	struct wmid3_gds_input_param params = {
+		.function_num = 0x1,
+		.hotkey_number = 0x01,
+		.devices = device,
+	};
+	struct acpi_buffer input = {
+		sizeof(struct wmid3_gds_input_param),
+		&params
+	};
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output.pointer;
+
+	if (!obj)
+		return AE_ERROR;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return AE_ERROR;
+	}
+	if (obj->buffer.length != 8) {
+		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
+		kfree(obj);
+		return AE_ERROR;
+	}
+
+	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	if (return_value.error_code || return_value.ec_return_value)
+		pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
+			return_value.error_code,
+			return_value.ec_return_value);
+	else
+		*value = !!(return_value.devices & device);
+
+	return status;
+}
+
+static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)
+{
+	u16 device;
+
+	switch (cap) {
+	case ACER_CAP_WIRELESS:
+		device = ACER_WMID3_GDS_WIRELESS;
+		break;
+	case ACER_CAP_BLUETOOTH:
+		device = ACER_WMID3_GDS_BLUETOOTH;
+		break;
+	case ACER_CAP_THREEG:
+		device = ACER_WMID3_GDS_THREEG;
+		break;
+	default:
+		return AE_ERROR;
+	}
+	return wmid3_get_device_status(value, device);
+}
+
+static acpi_status wmid3_set_device_status(u32 value, u16 device)
+{
+	struct wmid3_gds_return_value return_value;
+	acpi_status status;
+	union acpi_object *obj;
+	u16 devices;
+	struct wmid3_gds_input_param params = {
+		.function_num = 0x1,
+		.hotkey_number = 0x01,
+		.devices = ACER_WMID3_GDS_WIRELESS |
+				ACER_WMID3_GDS_THREEG |
+				ACER_WMID3_GDS_WIMAX |
+				ACER_WMID3_GDS_BLUETOOTH,
+	};
+	struct acpi_buffer input = {
+		sizeof(struct wmid3_gds_input_param),
+		&params
+	};
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output.pointer;
+
+	if (!obj)
+		return AE_ERROR;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return AE_ERROR;
+	}
+	if (obj->buffer.length != 8) {
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+		kfree(obj);
+		return AE_ERROR;
+	}
+
+	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	if (return_value.error_code || return_value.ec_return_value) {
+		pr_warning("Get Current Device Status failed: "
+			"0x%x - 0x%x\n", return_value.error_code,
+			return_value.ec_return_value);
+		return status;
+	}
+
+	devices = return_value.devices;
+	params.function_num = 0x2;
+	params.hotkey_number = 0x01;
+	params.devices = (value) ? (devices | device) : (devices & ~device);
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	obj = output2.pointer;
+
+	if (!obj)
+		return AE_ERROR;
+	else if (obj->type != ACPI_TYPE_BUFFER) {
+		kfree(obj);
+		return AE_ERROR;
+	}
+	if (obj->buffer.length != 4) {
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
+		kfree(obj);
+		return AE_ERROR;
+	}
+
+	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
+	kfree(obj);
+
+	if (return_value.error_code || return_value.ec_return_value)
+		pr_warning("Set Device Status failed: "
+			"0x%x - 0x%x\n", return_value.error_code,
+			return_value.ec_return_value);
+
+	return status;
+}
+
+static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
+{
+	u16 device;
+
+	switch (cap) {
+	case ACER_CAP_WIRELESS:
+		device = ACER_WMID3_GDS_WIRELESS;
+		break;
+	case ACER_CAP_BLUETOOTH:
+		device = ACER_WMID3_GDS_BLUETOOTH;
+		break;
+	case ACER_CAP_THREEG:
+		device = ACER_WMID3_GDS_THREEG;
+		break;
+	default:
+		return AE_ERROR;
+	}
+	return wmid3_set_device_status(value, device);
+}
+
 static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
 {
 	struct hotkey_function_type_aa *type_aa;
@@ -913,17 +1084,11 @@ static acpi_status WMID_set_capabilities(void)
 		return AE_ERROR;
 	}
 
-	dmi_walk(type_aa_dmi_decode, NULL);
-	if (!has_type_aa) {
-		interface->capability |= ACER_CAP_WIRELESS;
-		if (devices & 0x40)
-			interface->capability |= ACER_CAP_THREEG;
-		if (devices & 0x10)
-			interface->capability |= ACER_CAP_BLUETOOTH;
-	}
-
-	/* WMID always provides brightness methods */
-	interface->capability |= ACER_CAP_BRIGHTNESS;
+	interface->capability |= ACER_CAP_WIRELESS;
+	if (devices & 0x40)
+		interface->capability |= ACER_CAP_THREEG;
+	if (devices & 0x10)
+		interface->capability |= ACER_CAP_BLUETOOTH;
 
 	if (!(devices & 0x20))
 		max_brightness = 0x9;
@@ -936,6 +1101,10 @@ static struct wmi_interface wmid_interface = {
 	.type = ACER_WMID,
 };
 
+static struct wmi_interface wmid_v2_interface = {
+	.type = ACER_WMID_v2,
+};
+
 /*
  * Generic Device (interface-independent)
  */
@@ -956,6 +1125,14 @@ static acpi_status get_u32(u32 *value, u32 cap)
 	case ACER_WMID:
 		status = WMID_get_u32(value, cap, interface);
 		break;
+	case ACER_WMID_v2:
+		if (cap & (ACER_CAP_WIRELESS |
+			   ACER_CAP_BLUETOOTH |
+			   ACER_CAP_THREEG))
+			status = wmid_v2_get_u32(value, cap);
+		else if (wmi_has_guid(WMID_GUID2))
+			status = WMID_get_u32(value, cap, interface);
+		break;
 	}
 
 	return status;
@@ -989,6 +1166,13 @@ static acpi_status set_u32(u32 value, u32 cap)
 			}
 		case ACER_WMID:
 			return WMID_set_u32(value, cap, interface);
+		case ACER_WMID_v2:
+			if (cap & (ACER_CAP_WIRELESS |
+				   ACER_CAP_BLUETOOTH |
+				   ACER_CAP_THREEG))
+				return wmid_v2_set_u32(value, cap);
+			else if (wmi_has_guid(WMID_GUID2))
+				return WMID_set_u32(value, cap, interface);
 		default:
 			return AE_BAD_PARAMETER;
 		}
@@ -1095,186 +1279,6 @@ static void acer_backlight_exit(void)
 	backlight_device_unregister(acer_backlight_device);
 }
 
-static acpi_status wmid3_get_device_status(u32 *value, u16 device)
-{
-	struct wmid3_gds_return_value return_value;
-	acpi_status status;
-	union acpi_object *obj;
-	struct wmid3_gds_input_param params = {
-		.function_num = 0x1,
-		.hotkey_number = 0x01,
-		.devices = device,
-	};
-	struct acpi_buffer input = {
-		sizeof(struct wmid3_gds_input_param),
-		&params
-	};
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-
-	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = output.pointer;
-
-	if (!obj)
-		return AE_ERROR;
-	else if (obj->type != ACPI_TYPE_BUFFER) {
-		kfree(obj);
-		return AE_ERROR;
-	}
-	if (obj->buffer.length != 8) {
-		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
-		kfree(obj);
-		return AE_ERROR;
-	}
-
-	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
-	kfree(obj);
-
-	if (return_value.error_code || return_value.ec_return_value)
-		pr_warn("Get Device Status failed: 0x%x - 0x%x\n",
-			return_value.error_code,
-			return_value.ec_return_value);
-	else
-		*value = !!(return_value.devices & device);
-
-	return status;
-}
-
-static acpi_status get_device_status(u32 *value, u32 cap)
-{
-	if (wmi_has_guid(WMID_GUID3)) {
-		u16 device;
-
-		switch (cap) {
-		case ACER_CAP_WIRELESS:
-			device = ACER_WMID3_GDS_WIRELESS;
-			break;
-		case ACER_CAP_BLUETOOTH:
-			device = ACER_WMID3_GDS_BLUETOOTH;
-			break;
-		case ACER_CAP_THREEG:
-			device = ACER_WMID3_GDS_THREEG;
-			break;
-		default:
-			return AE_ERROR;
-		}
-		return wmid3_get_device_status(value, device);
-
-	} else {
-		return get_u32(value, cap);
-	}
-}
-
-static acpi_status wmid3_set_device_status(u32 value, u16 device)
-{
-	struct wmid3_gds_return_value return_value;
-	acpi_status status;
-	union acpi_object *obj;
-	u16 devices;
-	struct wmid3_gds_input_param params = {
-		.function_num = 0x1,
-		.hotkey_number = 0x01,
-		.devices = ACER_WMID3_GDS_WIRELESS |
-				ACER_WMID3_GDS_THREEG |
-				ACER_WMID3_GDS_WIMAX |
-				ACER_WMID3_GDS_BLUETOOTH,
-	};
-	struct acpi_buffer input = {
-		sizeof(struct wmid3_gds_input_param),
-		&params
-	};
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-	struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };
-
-	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = output.pointer;
-
-	if (!obj)
-		return AE_ERROR;
-	else if (obj->type != ACPI_TYPE_BUFFER) {
-		kfree(obj);
-		return AE_ERROR;
-	}
-	if (obj->buffer.length != 8) {
-		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
-		kfree(obj);
-		return AE_ERROR;
-	}
-
-	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
-	kfree(obj);
-
-	if (return_value.error_code || return_value.ec_return_value) {
-		pr_warning("Get Current Device Status failed: "
-			"0x%x - 0x%x\n", return_value.error_code,
-			return_value.ec_return_value);
-		return status;
-	}
-
-	devices = return_value.devices;
-	params.function_num = 0x2;
-	params.hotkey_number = 0x01;
-	params.devices = (value) ? (devices | device) : (devices & ~device);
-
-	status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output2);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = output2.pointer;
-
-	if (!obj)
-		return AE_ERROR;
-	else if (obj->type != ACPI_TYPE_BUFFER) {
-		kfree(obj);
-		return AE_ERROR;
-	}
-	if (obj->buffer.length != 4) {
-		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
-		kfree(obj);
-		return AE_ERROR;
-	}
-
-	return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);
-	kfree(obj);
-
-	if (return_value.error_code || return_value.ec_return_value)
-		pr_warning("Set Device Status failed: "
-			"0x%x - 0x%x\n", return_value.error_code,
-			return_value.ec_return_value);
-
-	return status;
-}
-
-static acpi_status set_device_status(u32 value, u32 cap)
-{
-	if (wmi_has_guid(WMID_GUID3)) {
-		u16 device;
-
-		switch (cap) {
-		case ACER_CAP_WIRELESS:
-			device = ACER_WMID3_GDS_WIRELESS;
-			break;
-		case ACER_CAP_BLUETOOTH:
-			device = ACER_WMID3_GDS_BLUETOOTH;
-			break;
-		case ACER_CAP_THREEG:
-			device = ACER_WMID3_GDS_THREEG;
-			break;
-		default:
-			return AE_ERROR;
-		}
-		return wmid3_set_device_status(value, device);
-
-	} else {
-		return set_u32(value, cap);
-	}
-}
-
 /*
  * Rfkill devices
  */
@@ -1301,8 +1305,7 @@ static void acer_rfkill_update(struct work_struct *ignored)
 	}
 
 	if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {
-		status = wmid3_get_device_status(&state,
-				ACER_WMID3_GDS_THREEG);
+		status = get_u32(&state, ACER_WMID3_GDS_THREEG);
 		if (ACPI_SUCCESS(status))
 			rfkill_set_sw_state(threeg_rfkill, !state);
 	}
@@ -1316,7 +1319,7 @@ static int acer_rfkill_set(void *data, bool blocked)
 	u32 cap = (unsigned long)data;
 
 	if (rfkill_inited) {
-		status = set_device_status(!blocked, cap);
+		status = set_u32(!blocked, cap);
 		if (ACPI_FAILURE(status))
 			return -ENODEV;
 	}
@@ -1343,7 +1346,7 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
 	if (!rfkill_dev)
 		return ERR_PTR(-ENOMEM);
 
-	status = get_device_status(&state, cap);
+	status = get_u32(&state, cap);
 
 	err = rfkill_register(rfkill_dev);
 	if (err) {
@@ -1464,6 +1467,8 @@ static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
 		return sprintf(buf, "AMW0 v2\n");
 	case ACER_WMID:
 		return sprintf(buf, "WMID\n");
+	case ACER_WMID_v2:
+		return sprintf(buf, "WMID v2\n");
 	default:
 		return sprintf(buf, "Error!\n");
 	}
@@ -1883,12 +1888,20 @@ static int __init acer_wmi_init(void)
 	if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))
 		interface = &wmid_interface;
 
+	if (wmi_has_guid(WMID_GUID3))
+		interface = &wmid_v2_interface;
+
+	if (interface)
+		dmi_walk(type_aa_dmi_decode, NULL);
+
 	if (wmi_has_guid(WMID_GUID2) && interface) {
-		if (ACPI_FAILURE(WMID_set_capabilities())) {
+		if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {
 			pr_err("Unable to detect available WMID devices\n");
 			return -ENODEV;
 		}
-	} else if (!wmi_has_guid(WMID_GUID2) && interface) {
+		/* WMID always provides brightness methods */
+		interface->capability |= ACER_CAP_BRIGHTNESS;
+	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
 		pr_err("No WMID device detection method found\n");
 		return -ENODEV;
 	}
@@ -1912,7 +1925,7 @@ static int __init acer_wmi_init(void)
 
 	set_quirks();
 
-	if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
+	if (acpi_video_backlight_support()) {
 		interface->capability &= ~ACER_CAP_BRIGHTNESS;
 		pr_info("Brightness must be controlled by "
 		       "generic video driver\n");
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 16+ messages in thread
[parent not found: <4E25AFC7020000230002F7D1@novprvlin0050.provo.novell.com>]

end of thread, other threads:[~2011-09-07  5:29 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-11  6:58 [Fwd: Re: A problem about acer-wmi] Joey Lee
2011-08-11  7:45 ` AceLan Kao
2011-08-11  8:02   ` Joey Lee
2011-08-11  8:49     ` AceLan Kao
2011-09-07  2:33   ` joeyli
2011-09-07  5:29     ` AceLan Kao
  -- strict thread matches above, loose matches on Subject: below --
2011-08-11  3:30 Joey Lee
2011-08-10 10:02 Joey Lee
2011-08-11  2:48 ` AceLan Kao
2011-08-10  9:17 Joey Lee
     [not found] <4E25AFC7020000230002F7D1@novprvlin0050.provo.novell.com>
2011-08-09  2:05 ` AceLan Kao
2011-08-09  2:07   ` AceLan Kao
2011-08-09  2:14   ` joeyli
2011-08-09  6:33     ` AceLan Kao
2011-08-10  2:13       ` joeyli
2011-08-10  8:49         ` joeyli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.