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), > + ¶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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html