/sys/devices/ 下的设备name就是bios中定义的HID

本文详细解析了ACPI设备加载过程中涉及的关键函数及其实现原理,包括acpi_add_single_object、acpi_init_device_object等函数的具体实现,并介绍了如何通过这些函数获取设备的HID/CID等信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ACPI scan的时候会调用到acpi_bus_check_add->acpi_add_single_object
static int acpi_add_single_object(struct acpi_device **child,
				  acpi_handle handle, int type,
				  unsigned long long sta)
{
	int result;
	struct acpi_device *device;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

	device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
	if (!device) {
		printk(KERN_ERR PREFIX "Memory allocation error\n");
		return -ENOMEM;
	}
//重点函数
	acpi_init_device_object(device, handle, type, sta);
	acpi_bus_get_power_flags(device);
	acpi_bus_get_wakeup_device_flags(device);
//重点函数
	result = acpi_device_add(device, acpi_device_release);
	if (result) {
		acpi_device_release(&device->dev);
		return result;
	}
}
我们先看第一个函数acpi_init_device_object->acpi_set_pnp_ids
static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
				int device_type)
{
	acpi_status status;
	struct acpi_device_info *info;
	struct acpi_pnp_device_id_list *cid_list;
	int i;

	switch (device_type) {
	case ACPI_BUS_TYPE_DEVICE:
		if (handle == ACPI_ROOT_OBJECT) {
			acpi_add_id(pnp, ACPI_SYSTEM_HID);
			break;
		}
//调用acpi_get_object_info得到设备的HID/CID等信息
		status = acpi_get_object_info(handle, &info);
		if (ACPI_FAILURE(status)) {
			pr_err(PREFIX "%s: Error reading device info\n",
					__func__);
			return;
		}
//如果acpi_get_object_info 中会置为ACPI_VALID_HID,则通过acpi_add_id将设备的hardware_id保持到device->pnp中
		if (info->valid & ACPI_VALID_HID) {
			acpi_add_id(pnp, info->hardware_id.string);
			pnp->type.platform_id = 1;
		}
}

acpi_status
acpi_get_object_info(acpi_handle handle,
		     struct acpi_device_info **return_buffer)
{
	struct acpi_namespace_node *node;
	struct acpi_device_info *info;
	struct acpi_pnp_device_id_list *cid_list = NULL;
	struct acpi_pnp_device_id *hid = NULL;
	struct acpi_pnp_device_id *uid = NULL;
	struct acpi_pnp_device_id *cls = NULL;
	char *next_id_string;
	acpi_object_type type;
	acpi_name name;
	u8 param_count = 0;
	u16 valid = 0;
	u32 info_size;
	u32 i;
	acpi_status status;

	/* Parameter validation */

	if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
		//得到HID/CID 等信息
		status = acpi_ut_execute_HID(node, &hid);
		if (ACPI_SUCCESS(status)) {
			info_size += hid->length;
			valid |= ACPI_VALID_HID;
		}

		/* Execute the Device._UID method */

		status = acpi_ut_execute_UID(node, &uid);
		if (ACPI_SUCCESS(status)) {
			info_size += uid->length;
			valid |= ACPI_VALID_UID;
		}

		

	/*
	 * Now that we have the variable-length data, we can allocate the
	 * return buffer
	 */
	info = ACPI_ALLOCATE_ZEROED(info_size);
	if (!info) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	
	if (hid) {
如果HID 不为null,则通过acpi_ns_copy_device_id将bios中定义的HID 赋值给hardware_id,也就是说kernel中的hardware_id就是bios中的HID
		next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
							hid, next_id_string);

		if (acpi_ut_is_pci_root_bridge(hid->string)) {
			info->flags |= ACPI_PCI_ROOT_BRIDGE;
		}
	}

	if (uid) {
		next_id_string = acpi_ns_copy_device_id(&info->unique_id,
							uid, next_id_string);
	}

	}

再看
static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
{
	struct acpi_hardware_id *id;

	id = kmalloc(sizeof(*id), GFP_KERNEL);
	if (!id)
		return;

	id->id = kstrdup_const(dev_id, GFP_KERNEL);
	if (!id->id) {
		kfree(id);
		return;
	}
将hid也就是hardware_id 保存到device的pnp->ids
	list_add_tail(&id->list, &pnp->ids);
	pnp->type.hardware_id = 1;
}
回到acpi_add_single_object 中继续调用acpi_device_add

首先通过
	list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) {
		if (!strcmp(acpi_device_bus_id->bus_id,
			    acpi_device_hid(device))) {
			acpi_device_bus_id->instance_no++;
			found = 1;
			kfree(new_bus_id);
			break;
		}
	}
找到是否有HID匹配,也就是说这里的acpi_device_bus_id->bus_id 其实就是等于HID。通过acpi_device_hid 就会得到当前设备的HID
const char *acpi_device_hid(struct acpi_device *device)
{
	struct acpi_hardware_id *hid;

	if (list_empty(&device->pnp.ids))
		return dummy_hid;

	hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
	return hid->id;
}
原来就是查device->pnp.ids,也就是想得到这个device的acpi_hardware_id。
回到acpi_device_add 中通过dev_set_name 来设置在/sys/devices/XXX下面的name
	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
通过前面的分析应该很容易得出这里的acpi_device_bus_id->bus_id 就是bios中定义的HID


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值