staticbool enable_5_button_array;
module_param(enable_5_button_array, bool, 0444);
MODULE_PARM_DESC(enable_5_button_array, "Enable 5 Button Array support. " "If you need this please report this to: platform-driver-x86@vger.kernel.org");
staticint enable_sw_tablet_mode = TABLET_SW_AUTO;
module_param(enable_sw_tablet_mode, int, 0444);
MODULE_PARM_DESC(enable_sw_tablet_mode, "Enable SW_TABLET_MODE reporting -1:auto 0:off 1:at-first-event 2:at-probe. " "If you need this please report this to: platform-driver-x86@vger.kernel.org");
/* When NOT in tablet mode, VGBS returns with the flag 0x40 */ #define TABLET_MODE_FLAG BIT(6)
/* * Some convertible use the intel-hid ACPI interface to report SW_TABLET_MODE, * these need to be compared via a DMI based authorization list because some * models have unreliable VGBS return which could cause incorrect * SW_TABLET_MODE report.
*/ staticconststruct dmi_system_id dmi_vgbs_allow_list[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 15-df0xxx"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite Dragonfly G2 Notebook PC"),
},
},
{ }
};
/* * Some devices, even non convertible ones, can send incorrect SW_TABLET_MODE * reports. Accept such reports only from devices in this list.
*/ staticconststruct dmi_system_id dmi_auto_add_switch[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31"/* Convertible */),
},
},
{
.matches = {
DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32"/* Detachable */),
},
},
{} /* Array terminator */
};
/* Enable|disable features - power button is always enabled */ if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN, enable)) {
dev_warn(device, "failed to %s hotkeys\n", str_enable_disable(enable)); return -EIO;
}
/* Query supported platform features */
status = acpi_evaluate_integer(handle, "BTNC", NULL, &button_cap); if (ACPI_FAILURE(status)) {
dev_warn(device, "failed to get button capability\n"); return;
}
/* Enable|disable features - power button is always enabled */ if (!intel_hid_execute_method(handle, INTEL_HID_DSM_BTNE_FN,
enable ? button_cap : 1))
dev_warn(device, "failed to set button capability\n");
}
/* * Some convertible have unreliable VGBS return which could cause incorrect * SW_TABLET_MODE report, in these cases we enable support when receiving * the first event instead of during driver setup.
*/ if (!priv->switches && enable_sw_tablet_mode == TABLET_SW_AT_EVENT &&
(event == 0xcc || event == 0xcd)) {
dev_info(&device->dev, "switch event received, enable switches supports\n");
err = intel_hid_switches_setup(device); if (err)
pr_err("Failed to setup Intel HID switches\n");
}
if (priv->wakeup_mode) { /* * Needed for wakeup from suspend-to-idle to work on some * platforms that don't expose the 5-button array, but still * send notifies with the power button event code to this * device object on power button actions while suspended.
*/ if (event == 0xce) goto wakeup;
/* * Some devices send (duplicate) tablet-mode events when moved * around even though the mode has not changed; and they do this * even when suspended. * Update the switch state in case it changed and then return * without waking up to avoid spurious wakeups.
*/ if (event == 0xcc || event == 0xcd) {
report_tablet_mode_event(priv->switches, event); return;
}
/* Wake up on 5-button array events only. */ if (event == 0xc0 || !priv->array) return;
ke = sparse_keymap_entry_from_scancode(priv->array, event); if (!ke) {
dev_info(&device->dev, "unknown event 0x%x\n", event); return;
}
if (ke->type == KE_IGNORE) return;
wakeup:
pm_wakeup_hard_event(&device->dev);
return;
}
/* * Needed for suspend to work on some platforms that don't expose * the 5-button array, but still send notifies with power button * event code to this device object on power button actions. * * Report the power button press and release.
*/ if (!priv->array) { if (event == 0xce) {
input_report_key(priv->input_dev, KEY_POWER, 1);
input_sync(priv->input_dev); return;
}
if (report_tablet_mode_event(priv->switches, event)) return;
/* 0xC0 is for HID events, other values are for 5 button array */ if (event != 0xc0) { if (!priv->array ||
!sparse_keymap_report_event(priv->array, event, 1, true))
dev_dbg(&device->dev, "unknown event 0x%x\n", event); return;
}
if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN,
&ev_index)) {
dev_warn(&device->dev, "failed to get event index\n"); return;
}
if (!sparse_keymap_report_event(priv->input_dev, ev_index, 1, true))
dev_dbg(&device->dev, "unknown event index 0x%llx\n",
ev_index);
}
if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V2_FN,
&event_cap)) { /* Check presence of 5 button array or v2 power button */ if (event_cap & 0x60000) returntrue;
}
if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V1_FN,
&event_cap)) { if (event_cap & 0x20000) returntrue;
}
if (enable_5_button_array || dmi_check_system(button_array_table)) returntrue;
if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDMM_FN, &mode)) {
dev_warn(&device->dev, "failed to read mode\n"); return -ENODEV;
}
if (mode != 0) { /* * This driver only implements "simple" mode. There appear * to be no other modes, but we should be paranoid and check * for compatibility.
*/
dev_info(&device->dev, "platform is not in simple mode\n"); return -ENODEV;
}
/* See dual_accel_detect.h for more info on the dual_accel check. */ if (enable_sw_tablet_mode == TABLET_SW_AUTO) { if (dmi_check_system(dmi_vgbs_allow_list))
enable_sw_tablet_mode = TABLET_SW_AT_PROBE; elseif (dmi_check_system(dmi_auto_add_switch) && !dual_accel_detect())
enable_sw_tablet_mode = TABLET_SW_AT_EVENT; else
enable_sw_tablet_mode = TABLET_SW_OFF;
}
err = intel_hid_input_setup(device); if (err) {
pr_err("Failed to setup Intel HID hotkeys\n"); return err;
}
/* Setup 5 button array */ if (button_array_present(device)) {
dev_info(&device->dev, "platform supports 5 button array\n");
err = intel_button_array_input_setup(device); if (err)
pr_err("Failed to setup Intel 5 button array hotkeys\n");
}
/* Setup switches for devices that we know VGBS return correctly */ if (enable_sw_tablet_mode == TABLET_SW_AT_PROBE) {
dev_info(&device->dev, "platform supports switches\n");
err = intel_hid_switches_setup(device); if (err)
pr_err("Failed to setup Intel HID switches\n"); else
report_tablet_mode_state(device);
}
status = acpi_install_notify_handler(handle,
ACPI_DEVICE_NOTIFY,
notify_handler,
device); if (ACPI_FAILURE(status)) return -EBUSY;
err = intel_hid_set_enable(&device->dev, true); if (err) goto err_remove_notify;
intel_button_array_enable(&device->dev, true);
/* * Call button load method to enable HID power button * Always do this since it activates events on some devices without * a button array too.
*/ if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
dev_warn(&device->dev, "failed to enable HID power button\n");
device_init_wakeup(&device->dev, true); /* * In order for system wakeup to work, the EC GPE has to be marked as * a wakeup one, so do that here (this setting will persist, but it has * no effect until the wakeup mask is set for the EC GPE).
*/
acpi_ec_mark_gpe_for_wake(); return 0;
/* * Unfortunately, some laptops provide a _HID="INT33D5" device with * _CID="PNP0C02". This causes the pnpacpi scan driver to claim the * ACPI node, so no platform device will be created. The pnpacpi * driver rejects this device in subsequent processing, so no physical * node is created at all. * * As a workaround until the ACPI core figures out how to handle * this corner case, manually ask the ACPI platform device code to * claim the ACPI node.
*/ static acpi_status __init
check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv)
{ conststruct acpi_device_id *ids = context; struct acpi_device *dev = acpi_fetch_acpi_dev(handle);
if (dev && acpi_match_device_ids(dev, ids) == 0) if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
dev_info(&dev->dev, "intel-hid: created platform device\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.