我是设备驱动程序的新手,我正在学习这个container_of和dev_get_drvdata,偶然发现了这个驱动程序。我删除了这个驱动程序的一部分,以使它更紧凑。
static void tsl4531_polling_worker(struct work_struct *work)
{
u8 buf[2];
struct tsl4531_data *data = container_of(to_delayed_work(work),
struct tsl4531_data, work);
mutex_lock(&data->update_lock);
buf[0] = DEVICE_LIGHT;
buf[1] = GET_REQUEST;
sam4l_send_request(data->pdata.sam4l,2,buf);
mutex_unlock(&data->update_lock);
}
static ssize_t store_enable_value(struct device *dev,struct device_attribute *devattr,const char *buf,size_t count){
struct tsl4531_data *data = dev_get_drvdata(dev);
if((buf[0] == '1') && (!tsl4531_enabled)) {
schedule_delayed_work(&data->work, msecs_to_jiffies(50));
tsl4531_enabled = 1;
} else if (buf[0] == '0'){
tsl4531_enabled = 0;
cancel_delayed_work_sync(&data->work);
tsl4531_lux = 0;
}
return count;
}
static DEVICE_ATTR(enable,S_IRUGO | S_IWUGO,
show_enable_value, store_enable_value );
static struct attribute *tsl4531_attributes[] = {
&dev_attr_lux_show.attr,
&dev_attr_enable.attr,
NULL
};
static const struct attribute_group tsl4531_attr_group = {
.attrs = tsl4531_attributes,
};
void tsl4531_callback_fun(struct work_struct *work)
{
struct tsl4531_data *chip = container_of(work,struct tsl4531_data,
pdata.work.work);
tsl4531_lux = chip->pdata.response[2];//Need to check on which response index we get lux value
input_report_abs(tsl4531_dev, ABS_X,tsl4531_lux);
input_sync(tsl4531_dev);
schedule_delayed_work(&chip->work, msecs_to_jiffies(1500));
}
static int __devinit tsl4531_probe(struct platform_device *pdev){
struct tsl4531_data *chip;
int err=0;
chip = kzalloc(sizeof(struct tsl4531_data), GFP_KERNEL);
if (!chip){
dev_dbg(&pdev->dev, "memory not allocated for tsl4531 light sensor module.\n");
return -ENOMEM;
}
dev_set_drvdata(&pdev->dev,chip);//here we give address in chip to struct device
tsl4531_dev=input_allocate_device();
if(!tsl4531_dev) {
dev_dbg(&pdev->dev, "memory not allocated for tsl4531_dev.\n");
return -ENOMEM;
}
err=input_register_device(tsl4531_dev);
if(err){
dev_dbg(&pdev->dev, "input register poll the device failed ... \n");
goto err_reg_poll;
}
mutex_init(&chip->update_lock);
err = sysfs_create_group(&pdev->dev.kobj,&tsl4531_attr_group);
if (err){
dev_dbg(&pdev->dev, "creating sysfs group for tsl4531 sensor module failed.\n");
goto exit_err;
}
INIT_DELAYED_WORK(&chip->work, tsl4531_polling_worker);
INIT_DELAYED_WORK(&chip->pdata.work,tsl4531_callback_fun);
chip->pdata.dev_id = DEVICE_LIGHT;
return 0;
return err;
}
static int __devexit tsl4531_remove(struct platform_device *pdev){
struct tsl4531_data *data = dev_get_drvdata(&pdev->dev);
cancel_delayed_work_sync(&data->work);
cancel_delayed_work(&data->pdata.work);
sysfs_remove_group(&pdev->dev.kobj, &tsl4531_attr_group);
unregister_sam4l_client(&data->pdata);
kfree(data);
return 0;
}
static const struct platform_device_id tsl4531_id[] = {
{ "tsl45317", 0 },
{ }
};
static struct platform_driver tsl4531_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "tsl45317",
},
.probe = tsl4531_probe,
.remove = tsl4531_remove,
.suspend = tsl4531_suspend,
.resume = tsl4531_resume,
.id_table = tsl4531_id,
};
static int __init tsl4531_init(void){
return platform_driver_register(&tsl4531_driver);
}
static void __exit tsl4531_exit(void){
platform_driver_unregister(&tsl4531_driver);
}关于container_of和dev_get_drvdata的工作,我没有什么疑问
1)在polling_worker函数中,我们可以看到一个探测宏,它将地址提取到原始结构并分配给结构tsl4531_data *data;2)在探测函数中,我们可以看到对dev_set_drvdata以及store_enable_value和tsl4531 dev_get_drvdata的一次调用。
在这里,container_of、dev_set和dev_get不是都在做同样的事情吗?
发布于 2014-07-31 16:44:46
container_of和dev_set, dev_get是不同的。但是,是的,意图可能是相同的。两者实际上都用于检索指针(通常指向设备的私有数据结构)。
container_of()实际上做了一个反向映射。它做与&struct_base->member操作相反的操作。在前面的操作中,您有指向结构基址的指针,并且需要它的一个成员的地址。而container_of接受成员的地址并返回基地址。在tsl4531_polling_worker()函数中,它有成员的地址,并使用container_of获取结构的基地址(struct tsl4531_data)
dev_set_drvdata()通常用来保存指针的地址,这样以后就可以使用dev_get_drvdata()检索它。与反向映射不同,函数从void *类型的指针存储和加载地址(请参阅http://lxr.free-electrons.com/source/drivers/base/dd.c#L595)
https://stackoverflow.com/questions/24903012
复制相似问题