本文共 3727 字,大约阅读时间需要 12 分钟。
acpi_get_devices(const char *HID, acpi_walk_callback user_function, void *context, void **return_value) 根据形参指定的参数返回一个acpi_device,其中的HID 可能为null其源码分析如下:acpi_statusacpi_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_statusacpi_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);}
转载地址:http://dcnmi.baihongyu.com/