android device 注册、添加、管理

注册:函数调用

设备挂到电源管理的函数调用关系是(依次往下调用)

audio_card_init (函数类型包含__init 初始化调用)

platform_device_add

device_add

device_pm_add

list_add_tail(最直接的链表添加操作)

 

以音频设备注册为例,音频声卡初始化

代码目录:kernel/sound/soc/xxxx.c

static int __init audio_card_init(void)
{
	int ret =0;	
	xxxx_snd_device = platform_device_alloc("soc-audio", -1);
	if (!xxxx_snd_device) {
		  ret = -ENOMEM;
		  return ret;
	}
	platform_set_drvdata(xxxx_snd_device, &xxxx_snd_devdata);
	xxxx_snd_devdata.dev = &xxxx_snd_device->dev;
	ret = platform_device_add(xxxx_snd_device);
	if (ret) {
	    platform_device_put(xxxx_snd_device);
	}
	return ret;
}



平台注册

代码目录:kernel/drivers/base/platform.c

/**
 * platform_device_add - add a platform device to device hierarchy
 * @pdev: platform device we're adding
 *
 * This is part 2 of platform_device_register(), though may be called
 * separately _iff_ pdev was allocated by platform_device_alloc().
 */
int platform_device_add(struct platform_device *pdev)
{
//...
	ret = device_add(&pdev->dev);
	if (ret == 0)
		return ret;

//...
	return ret;
}
EXPORT_SYMBOL_GPL(platform_device_add);


设备添加

代码目录:kernel/drivers/base/core.c

/**
 * device_add - add device to device hierarchy.
 * @dev: device.
 *
 * This is part 2 of device_register(), though may be called
 * separately _iff_ device_initialize() has been called separately.
 *
 * This adds @dev to the kobject hierarchy via kobject_add(), adds it
 * to the global and sibling lists for the device, then
 * adds it to the other relevant subsystems of the driver model.
 *
 * NOTE: _Never_ directly free @dev after calling this function, even
 * if it returned an error! Always use put_device() to give up your
 * reference instead.
 */
int device_add(struct device *dev)
{
//...
	device_pm_add(dev);
//...
}


设备添加到电源管理链表中

代码目录:kernel/drivers/base/main.c

/**
 * device_pm_add - Add a device to the PM core's list of active devices.
 * @dev: Device to add to the list.
 */
void device_pm_add(struct device *dev)
{
	pr_debug("PM: Adding info for %s:%s\n",
		 dev->bus ? dev->bus->name : "No Bus",
		 kobject_name(&dev->kobj));
	mutex_lock(&dpm_list_mtx);
	if (dev->parent) {
		if (dev->parent->power.status >= DPM_SUSPENDING)
			dev_warn(dev, "parent %s should not be sleeping\n",
				 dev_name(dev->parent));
	} else if (transition_started) {
		/*
		 * We refuse to register parentless devices while a PM
		 * transition is in progress in order to avoid leaving them
		 * unhandled down the road
		 */
		dev_WARN(dev, "Parentless device registered during a PM transaction\n");
	}

	list_add_tail(&dev->power.entry, &dpm_list);
	mutex_unlock(&dpm_list_mtx);
}


应用:android休眠

1、state_store 调用 request_suspend_state,

 

2、然后request_suspend_state 调用early_suspend_work,完成一级休眠工作,

实际操作就是调用使用register_early_suspend注册的设备的suspend handle

比如触摸屏、按键、背光、重力感应等

 

3、early_suspend完成以后,

在函数末尾调用 wake_unlock(&main_wake_lock),释放掉非超时锁main_wake_lock,

如果应用程序没有不释放的锁了,就会调用到二级睡眠入口函数suspend

 

4、suspend调用pm_suspend,再调用enter_state

这里才是真正二级待机的入口了

 

5、在函数suspend_prepare完成冻结进程成功后,就到了关于非系统设备的suspend函数,

就是suspend_devices_and_enter

 

6、suspend_devices_and_enter进来以后先关掉控制器,

如果开发人员,此时就不能打出log了,为调试方便可以不关闭控制器;

dpm_suspend_start(PMSG_SUSPEND)就是和本文有关的函数入口了,

它要完成的工作是关闭所有(源代码是全部)非系统设备(non-sysdev),

里面的管理就是用到前面注册添加好的链表了

 

7、dpm_preparedpm_suspend类似,

只是前者是遍历链表置状态位标志status为prepare,调用设备的prepare函数;

后者是遍历链表置状态位标志status为suspend,调用设备的suspend函数

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值