展会信息港展会大全

android device 注册、添加、管理
来源:互联网   发布日期:2016-01-14 14:54:33   浏览:2377次  

导读:注册:函数调用以音频设备注册为例,音频声卡初始化代码目录:kernel/sound/soc/xxxx.cstatic int __init audio_card_init(void){int ret =0;xxxx_snd_device = platform_device_alloc(soc-audio, -1)......

注册:函数调用

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

代码目录: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(rk2818_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)

{

int i, ret = 0;

if (!pdev)

return -EINVAL;

if (!pdev->dev.parent)

pdev->dev.parent = &platform_bus;

pdev->dev.bus = &platform_bus_type;

if (pdev->id != -1)

dev_set_name(&pdev->dev, "%s.%d", pdev->name,pdev->id);

else

dev_set_name(&pdev->dev, "%s", pdev->name);

for (i = 0; i < pdev->num_resources; i++) {

struct resource *p, *r = &pdev->resource[i];

if (r->name == NULL)

r->name = dev_name(&pdev->dev);

p = r->parent;

if (!p) {

if (resource_type(r) == IORESOURCE_MEM)

p = &iomem_resource;

else if (resource_type(r) == IORESOURCE_IO)

p = &ioport_resource;

}

if (p && insert_resource(p, r)) {

printk(KERN_ERR

"%s: failed to claim resource %d\n",

dev_name(&pdev->dev), i);

ret = -EBUSY;

goto failed;

}

}

pr_debug("Registering platform device '%s'. Parent at %s\n",

dev_name(&pdev->dev), dev_name(pdev->dev.parent));

ret = device_add(&pdev->dev);

if (ret == 0)

return ret;

failed:

while (--i >= 0) {

struct resource *r = &pdev->resource[i];

unsigned long type = resource_type(r);

if (type == IORESOURCE_MEM || type == IORESOURCE_IO)

release_resource(r);

}

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)

{

struct device *parent = NULL;

struct class_interface *class_intf;

int error = -EINVAL;

dev = get_device(dev);

if (!dev)

goto done;

if (!dev->p) {

error = device_private_init(dev);

if (error)

goto done;

}

/*

* for statically allocated devices, which should all be converted

* some day, we need to initialize the name. We prevent reading back

* the name, and force the use of dev_name()

*/

if (dev->init_name) {

dev_set_name(dev, "%s", dev->init_name);

dev->init_name = NULL;

}

if (!dev_name(dev))

goto name_error;

pr_debug("device: '%s': %s\n", dev_name(dev), __func__);

parent = get_device(dev->parent);

setup_parent(dev, parent);

/* use parent numa_node */

if (parent)

set_dev_node(dev, dev_to_node(parent));

/* first, register with generic layer. */

/* we require the name to be set before, and pass NULL */

error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);

if (error)

goto Error;

/* notify platform of device entry */

if (platform_notify)

platform_notify(dev);

error = device_create_file(dev, &uevent_attr);

if (error)

goto attrError;

if (MAJOR(dev->devt)) {

error = device_create_file(dev, &devt_attr);

if (error)

goto ueventattrError;

error = device_create_sys_dev_entry(dev);

if (error)

goto devtattrError;

devtmpfs_create_node(dev);

}

error = device_add_class_symlinks(dev);

if (error)

goto SymlinkError;

error = device_add_attrs(dev);

if (error)

goto AttrsError;

error = bus_add_device(dev);

if (error)

goto BusError;

error = dpm_sysfs_add(dev);

if (error)

goto DPMError;

device_pm_add(dev);

/* Notify clients of device addition.This call must come

* after dpm_sysf_add() and before kobject_uevent().

*/

if (dev->bus)

blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

BUS_NOTIFY_ADD_DEVICE, dev);

kobject_uevent(&dev->kobj, KOBJ_ADD);

bus_probe_device(dev);

if (parent)

klist_add_tail(&dev->p->knode_parent,

&parent->p->klist_children);

if (dev->class) {

mutex_lock(&dev->class->p->class_mutex);

/* tie the class to the device */

klist_add_tail(&dev->knode_class,

&dev->class->p->class_devices);

/* notify any interfaces that the device is here */

list_for_each_entry(class_intf,

&dev->class->p->class_interfaces, node)

if (class_intf->add_dev)

class_intf->add_dev(dev, class_intf);

mutex_unlock(&dev->class->p->class_mutex);

}

done:

put_device(dev);

return error;

DPMError:

bus_remove_device(dev);

BusError:

device_remove_attrs(dev);

AttrsError:

device_remove_class_symlinks(dev);

SymlinkError:

if (MAJOR(dev->devt))

device_remove_sys_dev_entry(dev);

devtattrError:

if (MAJOR(dev->devt))

device_remove_file(dev, &devt_attr);

ueventattrError:

device_remove_file(dev, &uevent_attr);

attrError:

kobject_uevent(&dev->kobj, KOBJ_REMOVE);

kobject_del(&dev->kobj);

Error:

cleanup_device_parent(dev);

if (parent)

put_device(parent);

name_error:

kfree(dev->p);

dev->p = NULL;

goto done;

}

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

代码目录: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);

}

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

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

platform_device_add

device_add

device_pm_add

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

应用: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_prepare和dpm_suspend类似,

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

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

赞助本站

人工智能实验室

相关热词: device 注册 添加 管理

相关内容
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港