/* Returned when NOT in tablet mode on some HP Stream x360 11 models */ #define VGBS_TABLET_MODE_FLAG_ALT 0x10 /* When NOT in tablet mode, VGBS returns with the flag 0x40 */ #define VGBS_TABLET_MODE_FLAG 0x40 #define VGBS_DOCK_MODE_FLAG 0x80
staticconststruct key_entry intel_vbtn_switchmap[] = { /* * SW_DOCK should only be reported for docking stations, but DSDTs using the * intel-vbtn code, always seem to use this for 2-in-1s / convertibles and set * SW_DOCK=1 when in laptop-mode (in tandem with setting SW_TABLET_MODE=0). * This causes userspace to think the laptop is docked to a port-replicator * and to disable suspend-on-lid-close, which is undesirable. * Map the dock events to KEY_IGNORE to avoid this broken SW_DOCK reporting.
*/
{ KE_IGNORE, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */
{ KE_IGNORE, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
{ KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
{ KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
{ KE_END }
};
staticvoid detect_tablet_mode(struct device *dev)
{ struct intel_vbtn_priv *priv = dev_get_drvdata(dev);
acpi_handle handle = ACPI_HANDLE(dev); unsignedlonglong vgbs;
acpi_status status; int m;
status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs); if (ACPI_FAILURE(status)) return;
m = !(vgbs & VGBS_TABLET_MODE_FLAGS);
input_report_switch(priv->switches_dev, SW_TABLET_MODE, m);
m = (vgbs & VGBS_DOCK_MODE_FLAG) ? 1 : 0;
input_report_switch(priv->switches_dev, SW_DOCK, m);
input_sync(priv->switches_dev);
}
/* * Note this unconditionally creates the 2 input_dev-s and sets up * the sparse-keymaps. Only the registration is conditional on * have_buttons / have_switches. This is done so that the notify * handler can always call sparse_keymap_entry_from_scancode() * on the input_dev-s do determine the event type.
*/ staticint intel_vbtn_input_setup(struct platform_device *device)
{ struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); int ret;
priv->buttons_dev = devm_input_allocate_device(&device->dev); if (!priv->buttons_dev) return -ENOMEM;
ret = sparse_keymap_setup(priv->buttons_dev, intel_vbtn_keymap, NULL); if (ret) return ret;
if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) { if (!priv->has_buttons) {
dev_warn(&device->dev, "Warning: received 0x%02x button event on a device without buttons, please report this.\n",
event); return;
}
input_dev = priv->buttons_dev;
} elseif ((ke = sparse_keymap_entry_from_scancode(priv->switches_dev, event))) { if (!priv->has_switches) { /* See dual_accel_detect.h for more info */ if (priv->dual_accel) return;
dev_info(&device->dev, "Registering Intel Virtual Switches input-dev after receiving a switch event\n");
ret = input_register_device(priv->switches_dev); if (ret) return;
if (priv->wakeup_mode) {
pm_wakeup_hard_event(&device->dev);
/* * Skip reporting an evdev event for button wake events, * mirroring how the drivers/acpi/button.c code skips this too.
*/ if (ke->type == KE_KEY) return;
}
/* * Even press events are autorelease if there is no corresponding odd * release event, or if the odd event is KE_IGNORE.
*/
ke_rel = sparse_keymap_entry_from_scancode(input_dev, event | 1);
autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
/* * There are several laptops (non 2-in-1) models out there which support VGBS, * but simply always return 0, which we translate to SW_TABLET_MODE=1. This in * turn causes userspace (libinput) to suppress events from the builtin * keyboard and touchpad, making the laptop essentially unusable. * * Since the problem of wrongly reporting SW_TABLET_MODE=1 in combination * with libinput, leads to a non-usable system. Where as OTOH many people will * not even notice when SW_TABLET_MODE is not being reported, a DMI based allow * list is used here. This list mainly matches on the chassis-type of 2-in-1s. * * There are also some 2-in-1s which use the intel-vbtn ACPI interface to report * SW_TABLET_MODE with a chassis-type of 8 ("Portable") or 10 ("Notebook"), * these are matched on a per model basis, since many normal laptops with a * possible broken VGBS ACPI-method also use these chassis-types.
*/ staticconststruct dmi_system_id dmi_switches_allow_list[] = {
{
.matches = {
DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31"/* Convertible */),
},
},
{
.matches = {
DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32"/* Detachable */),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7352"),
},
},
{} /* Array terminator */
};
staticbool intel_vbtn_has_switches(acpi_handle handle, bool dual_accel)
{ /* See dual_accel_detect.h for more info */ if (dual_accel) returnfalse;
if (!dmi_check_system(dmi_switches_allow_list)) returnfalse;
err = intel_vbtn_input_setup(device); if (err) {
pr_err("Failed to setup Intel Virtual Button\n"); return err;
}
status = acpi_install_notify_handler(handle,
ACPI_DEVICE_NOTIFY,
notify_handler,
device); if (ACPI_FAILURE(status)) return -EBUSY;
if (has_buttons) {
status = acpi_evaluate_object(handle, "VBDL", NULL, NULL); if (ACPI_FAILURE(status))
dev_err(&device->dev, "Error VBDL failed with ACPI status %d\n", status);
} // Check switches after buttons since VBDL may have side effects. if (has_switches)
detect_tablet_mode(&device->dev);
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;
}
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-vbtn: 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.