/* * There will be two events: * 0x02 - Button was pressed while device was off/sleeping. * 0x80 - Button was pressed while device was up.
*/ #define QUICKSTART_EVENT_RUNTIME 0x80
/* * Knowing what these buttons do require system specific knowledge. * This could be done by matching on DMI data in a long quirk table. * However, it is easier to leave it up to user space to figure this out. * * Using for example udev hwdb the scancode 0x1 can be remapped suitably.
*/ staticconststruct key_entry quickstart_keymap[] = {
{ KE_KEY, 0x1, { KEY_UNKNOWN } },
{ KE_END, 0 },
};
/* * The GHID ACPI method is used to indicate the "role" of the button. * However, all the meanings of these values are vendor defined. * * We do however expose this value to user space.
*/ staticint quickstart_get_ghid(struct quickstart_data *data)
{ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle = ACPI_HANDLE(data->dev); union acpi_object *obj;
acpi_status status; int ret = 0;
/* * This returns a buffer telling the button usage ID, * and triggers pending notify events (The ones before booting).
*/
status = acpi_evaluate_object_typed(handle, "GHID", NULL, &buffer, ACPI_TYPE_BUFFER); if (ACPI_FAILURE(status)) return -EIO;
obj = buffer.pointer; if (!obj) return -ENODATA;
/* * Quoting the specification: * "The GHID method can return a BYTE, WORD, or DWORD. * The value must be encoded in little-endian byte * order (least significant byte first)."
*/ switch (obj->buffer.length) { case 1:
data->id = obj->buffer.pointer[0]; break; case 2:
data->id = get_unaligned_le16(obj->buffer.pointer); break; case 4:
data->id = get_unaligned_le32(obj->buffer.pointer); break; default:
dev_err(data->dev,
FW_BUG "GHID method returned buffer of unexpected length %u\n",
obj->buffer.length);
ret = -EIO; break;
}
mutex_init(&data->input_lock);
ret = devm_add_action_or_reset(&pdev->dev, quickstart_mutex_destroy, &data->input_lock); if (ret < 0) return ret;
/* * We have to initialize the device wakeup before evaluating GHID because * doing so will notify the device if the button was used to wake the machine * from S5.
*/
device_init_wakeup(&pdev->dev, true);
ret = quickstart_get_ghid(data); if (ret < 0) return ret;
data->input_device = devm_input_allocate_device(&pdev->dev); if (!data->input_device) return -ENOMEM;
ret = sparse_keymap_setup(data->input_device, quickstart_keymap, NULL); if (ret < 0) return ret;
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.