drivers/platform/x86/quickstart.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/quickstart.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/quickstart.c
Extension
.c
Size
6214 bytes
Lines
238
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct quickstart_data {
	struct device *dev;
	struct mutex input_lock;	/* Protects input sequence during notify */
	struct input_dev *input_device;
	char input_name[32];
	char phys[32];
	u32 id;
};

/*
 * 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.
 */
static const struct key_entry quickstart_keymap[] = {
	{ KE_KEY, 0x1, { KEY_UNKNOWN } },
	{ KE_END, 0 },
};

static ssize_t button_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct quickstart_data *data = dev_get_drvdata(dev);

	return sysfs_emit(buf, "%u\n", data->id);
}
static DEVICE_ATTR_RO(button_id);

static struct attribute *quickstart_attrs[] = {
	&dev_attr_button_id.attr,
	NULL
};
ATTRIBUTE_GROUPS(quickstart);

static void quickstart_notify(acpi_handle handle, u32 event, void *context)
{
	struct quickstart_data *data = context;

	switch (event) {
	case QUICKSTART_EVENT_RUNTIME:
		mutex_lock(&data->input_lock);
		sparse_keymap_report_event(data->input_device, 0x1, 1, true);
		mutex_unlock(&data->input_lock);

		acpi_bus_generate_netlink_event(DRIVER_NAME, dev_name(data->dev), event, 0);
		break;
	default:
		dev_err(data->dev, FW_INFO "Unexpected ACPI notify event (%u)\n", event);
		break;
	}
}

/*
 * 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.
 */
static int 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:

Annotation

Implementation Notes