linux kernel - Device Specific Data Structure with Platform Driver and Character Device Interface -
i'm struggling understanding linkup between platform device driver character device interface , storing data in device specific data structure.
i created struct keeping track of data related device, , add devices struct @ probe function:
dev_set_drvdata(dev, data_struct);
i keep global copy of data_struct
.
i register misc device can mmap()
, access device through ioctl()
commands. if want access device's data_struct
, , access through global copy. there way through inode
or file
pointers access data stored in devices struct?
i allow 1 instance of device, want make sure implement correctly future implementations there might multiple devices using same driver.
when miscdevice being open first time, miscdevice framework set file->private_data
struct miscdevice
(see misc_open() function , comment misc_register() function). can rely on , use file->private_data
in file operations obtain custom structure, using container_of()
macro. of course, custom structure must contain struct miscdevice
that. neat , commonly used way create helper function called to_*()
, figure out , return custom struct file
pointer provided. if called custom struct my_struct
, should call helper function to_my_struct()
.
also, if writing platform driver, can use platform_set_drvdata()
instead of dev_set_drvdata()
. needed can obtain custom structure in remove()
function of platform driver.
here example explained above:
struct my_struct { struct platform_device *pdev; struct miscdevice mdev; }; static inline struct my_struct *to_my_struct(struct file *file) { struct miscdevice *miscdev = file->private_data; return container_of(miscdev, struct my_struct, mdev); } static ssize_t my_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { struct my_struct *my = to_my_struct(file); return simple_read_from_buffer(buf, count, pos, "my text", 7); } static const struct file_operations my_fops = { .owner = this_module, .read = my_read, }; static int my_probe(struct platform_device *pdev) { struct my_struct *my; int ret; = devm_kzalloc(&pdev->dev, sizeof(*my), gfp_kernel); if (!my) return -enomem; platform_set_drvdata(pdev, my); my->pdev = pdev; my->mdev.minor = misc_dynamic_minor; my->mdev.name = "my"; my->mdev.fops = &my_fops; my->mdev.parent = null; ret = misc_register(&my->mdev); if (ret) { dev_err(&pdev->dev, "failed register miscdev\n"); return ret; } dev_info(&pdev->dev, "registered\n"); return 0; } static int my_remove(struct platform_device *pdev) { struct my_struct *my = platform_get_drvdata(pdev); misc_deregister(&my->mdev); dev_info(&pdev->dev, "unregistered\n"); return 0; }
by way, can examples in kernel code, using keywords, this:
$ git grep -l --all-match -e 'misc_register(' -e 'platform_device' -e 'file->private_data' -- drivers/
Comments
Post a Comment