acpi_get_devices(const char *HID, acpi_walk_callback user_function, void *context, void **return_value) 根据形参指定的参数返回一个acpi_device,其中的HID 可能为null
其源码分析如下:
acpi_status
acpi_get_devices(const char *HID,
acpi_walk_callback user_function,
void *context, void **return_value)
{
acpi_status status;
struct acpi_get_devices_info info;
ACPI_FUNCTION_TRACE(acpi_get_devices);
/* Parameter validation */
#可以看到形参hid可以为null,但是user_function 不能为null
if (!user_function) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* We're going to call their callback from OUR callback, so we need
* to know what it is, and their context parameter.
*/
#用形参给info赋值
info.hid = HID;
info.context = context;
info.user_function = user_function;
/*
* Lock the namespace around the walk.
* The namespace will be unlocked/locked around each call
* to the user function - since this function
* must be allowed to make Acpi calls itself.
*/
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
#开始从root 遍历所有类型为device的设备,来匹配info中的信息以寻找对应的acpi_device,结果保存在return_value中返回
status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
acpi_ns_get_device_callback, NULL,
&info, return_value);
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
我们继续看看acpi_ns_walk_namespace 中为查找acpi_device所有的callback函数
static acpi_status
acpi_ns_get_device_callback(acpi_handle obj_handle,
u32 nesting_level,
void *context, void **return_value)
{
struct acpi_get_devices_info *info = context;
acpi_status status;
struct acpi_namespace_node *node;
u32 flags;
struct acpi_pnp_device_id *hid;
struct acpi_pnp_device_id_list *cid;
u32 i;
u8 found;
int no_match;
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return (status);
}
#检查handle是否有效
node = acpi_ns_validate_handle(obj_handle);
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return (status);
}
if (!node) {
return (AE_BAD_PARAMETER);
}
#search acpi_device分为两种情况,首先查找HID,如果没有查找到HID或者HID 为null,则开始执行user function查找
if (info->hid != NULL) {
#得到node的hid
status = acpi_ut_execute_HID(node, &hid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
} else if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
#hid就是一个字符串,这里通过strcmp比较字符串是否相等
no_match = strcmp(hid->string, info->hid);
ACPI_FREE(hid);
#如果hid没有找到,则继续找cid,从for循环可以看出一个hid可以对应多个cid
if (no_match) {
/*
* HID does not match, attempt match within the
* list of Compatible IDs (CIDs)
*/
status = acpi_ut_execute_CID(node, &cid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
} else if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
/* Walk the CID list */
#遍历所有的cid
found = FALSE;
for (i = 0; i < cid->count; i++) {
if (strcmp(cid->ids[i].string, info->hid) == 0) {
/* Found a matching CID */
found = TRUE;
break;
}
}
ACPI_FREE(cid);
if (!found) {
return (AE_OK);
}
}
}
/* Run _STA to determine if device is present */
#如果hid和cid 都没有匹配,则执行STA 来判断这个device是否存在
status = acpi_ut_execute_STA(node, &flags);
if (ACPI_FAILURE(status)) {
return (AE_CTRL_DEPTH);
}
if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
!(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
/*
* Don't examine the children of the device only when the
* device is neither present nor functional. See ACPI spec,
* description of _STA for more information.
*/
return (AE_CTRL_DEPTH);
}
/* We have a valid device, invoke the user function */
#hid和cid 都没有匹配,而且STA返回ok的话,则执行用户指定的user_function来继续查找acpi_device
status = info->user_function(obj_handle, nesting_level,
info->context, return_value);
return (status);
}
内核ACPI函数API之acpi_get_devices
最新推荐文章于 2021-05-01 15:50:06 发布