972
edits
[unchecked revision] | [unchecked revision] |
m (Bot: Replace deprecated source tag with syntaxhighlight) |
|||
(17 intermediate revisions by 2 users not shown) | |||
Line 35:
Below is an example of basic uACPI initialization sequence that enters ACPI mode, parses tables, brings the event system online, and finally loads & initializes the namespace.
<
#include <uacpi/uacpi.h>
#include <uacpi/event.h>
Line 53:
/*
* Set
*/
.
▲ * okay for now since we're just getting started. We can change this
▲ * to INFO later on, which is the recommended level for release
▲ * builds. There's also the loudest UACPI_LOG_DEBUG log level, which
▲ * is recommended to pin down lockups or hangs.
};
Line 123 ⟶ 118:
return 0;
}
</syntaxhighlight>
== Code examples ==
=== Namespace Enumeration & Finding Devices ===
There
==== Let Devices Discover Themselves ====
Line 135 ⟶ 130:
so that it's called by kernel code during initialization.
<
// ps2k.c
#include <uacpi/utilities.h>
#include <uacpi/resources.h>
Line 148 ⟶ 144:
uacpi_status ret = uacpi_get_current_resources(node, &kb_res);
if (uacpi_unlikely_error(ret)) {
log_error("unable to
return UACPI_NS_ITERATION_DECISION_NEXT_PEER;
}
Line 166 ⟶ 162:
uacpi_find_devices(PS2K_PNP_ID, match_ps2k, NULL);
}
</syntaxhighlight>
<syntaxhighlight lang="c">
// acpi_init.c
find_ps2_keyboard();▼
void find_acpi_devices(void) {
find_ps2_mouse();▼
▲ find_ps2_keyboard();
find_i2c();▼
▲ find_ps2_mouse();
find_power_button();▼
▲ find_i2c();
// ...and more▼
▲ find_power_button();
▲ // ...and more
}
</syntaxhighlight>
As you can see it's a very simple approach, but it has lots of drawbacks:
Line 184:
In this approach, we treat the ACPI namespace as a bus in our kernel, and let devices provide a way to identify them.
<
// acpi_bus.h
#include <uacpi/uacpi.h>
#include <uacpi/namespace.h>
#include <uacpi/utilities.h>▼
#include <uacpi/resources.h>▼
struct acpi_driver {
const char *device_name;
const char *const *pnp_ids;
int (*device_probe)(uacpi_namespace_node *node, uacpi_namespace_node_info *info);
struct acpi_driver *next;
Line 198 ⟶ 200:
void acpi_register_driver(struct acpi_driver *driver);
</syntaxhighlight>
<syntaxhighlight lang="c">
extern struct acpi_driver *acpi_drivers_head;▼
// ps2k.c
#include <acpi_bus.h>
▲#include <uacpi/resources.h>
#define PS2K_PNP_ID "PNP0303"
Line 212 ⟶ 213:
};
static int ps2k_probe(
{
uacpi_resources *kb_res;
Line 222 ⟶ 223:
* well!
*/
uacpi_status
if (uacpi_unlikely_error(
log_error("unable to
return -ENODEV;
}
Line 241 ⟶ 242:
};
/*
* This is called either manually by the kernel, or put in the linker script
* in some known section, and executed by the kernel as part of driver initcalls.
* If it's a dynamically loadable module, then this is called on module load.
*/
int ps2k_init(void)
{
acpi_register_driver(&ps2k_driver);
return 0;
}
</syntaxhighlight>
<syntaxhighlight lang="c">
// acpi_bus.c
#include <acpi_bus.h>
▲#include <uacpi/utilities.h>
void acpi_register_driver(struct acpi_driver *driver)
{
struct acpi_driver *next = acpi_drivers_head;
acpi_drivers_head = driver;
driver->next = next;
}
static uacpi_ns_iteration_decision acpi_init_one_device(void *ctx, uacpi_namespace_node *node)
Line 257 ⟶ 273:
uacpi_status ret = uacpi_get_namespace_node_info(node, &info);
if (uacpi_unlikely_error(ret)) {
const char *path = uacpi_namespace_node_generate_absolute_path(node);
log_error("unable to retrieve node %
uacpi_free_absolute_path(path);
return UACPI_NS_ITERATION_DECISION_CONTINUE;
}
Line 270 ⟶ 288:
struct acpi_driver *drv = NULL;
if (info->
// Match the HID against every existing acpi_driver pnp id list
}
if (drv == NULL && (info->
// Match the CID list against every existing acpi_driver pnp id list
}
Line 280 ⟶ 298:
if (drv != NULL) {
// Probe the driver and do something with the error code if desired
drv->
}
Line 290 ⟶ 308:
{
uacpi_namespace_for_each_node_depth_first(
uacpi_namespace_root(), acpi_init_one_device, UACPI_NULL
);
}
</syntaxhighlight>
As you can see above, this approach is more scalable, faster, and involves way less code duplication.
Line 300 ⟶ 317:
=== Shutting Down the System ===
<
#include <uacpi/sleep.h>
Line 340 ⟶ 357:
return 0;
}
</syntaxhighlight>
=== Hooking Up the Power Button ===
Line 346 ⟶ 363:
The example below hooks up the power button press using a fixed event callback.
<
#include <uacpi/event.h>
Line 379 ⟶ 396:
return 0;
}
</syntaxhighlight>
Note that some of the more modern hardware routes the power button in a more complicated way, via an embedded controller.
|