Re: [Fwd: Re: A problem about acer-wmi]

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

 



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.

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.

2011/8/10 Joey Lee <jlee@xxxxxxxxxx>:
> 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@xxxxxxxx>
> 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@xxxxxxxx>
> ---
>  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
>
>
>
>



-- 
Chia-Lin Kao(AceLan)
http://blog.acelan.idv.tw/
E-Mail: acelan.kaoATcanonical.com (s/AT/@/)
--
To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux