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 <[email protected]>:
> 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 <[email protected]>
> 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 <[email protected]>
> ---
> 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),
> + ¶ms
> + };
> + 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),
> + ¶ms
> + };
> + 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),
> - ¶ms
> - };
> - 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),
> - ¶ms
> - };
> - 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html