1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Media device node
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2010 Nokia Corporation
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
8*4882a593Smuzhiyun * Sakari Ailus <sakari.ailus@iki.fi>
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * --
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * Common functions for media-related drivers to register and unregister media
13*4882a593Smuzhiyun * device nodes.
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #ifndef _MEDIA_DEVNODE_H
17*4882a593Smuzhiyun #define _MEDIA_DEVNODE_H
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <linux/poll.h>
20*4882a593Smuzhiyun #include <linux/fs.h>
21*4882a593Smuzhiyun #include <linux/device.h>
22*4882a593Smuzhiyun #include <linux/cdev.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun struct media_device;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /*
27*4882a593Smuzhiyun * Flag to mark the media_devnode struct as registered. Drivers must not touch
28*4882a593Smuzhiyun * this flag directly, it will be set and cleared by media_devnode_register and
29*4882a593Smuzhiyun * media_devnode_unregister.
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun #define MEDIA_FLAG_REGISTERED 0
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /**
34*4882a593Smuzhiyun * struct media_file_operations - Media device file operations
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * @owner: should be filled with %THIS_MODULE
37*4882a593Smuzhiyun * @read: pointer to the function that implements read() syscall
38*4882a593Smuzhiyun * @write: pointer to the function that implements write() syscall
39*4882a593Smuzhiyun * @poll: pointer to the function that implements poll() syscall
40*4882a593Smuzhiyun * @ioctl: pointer to the function that implements ioctl() syscall
41*4882a593Smuzhiyun * @compat_ioctl: pointer to the function that will handle 32 bits userspace
42*4882a593Smuzhiyun * calls to the ioctl() syscall on a Kernel compiled with 64 bits.
43*4882a593Smuzhiyun * @open: pointer to the function that implements open() syscall
44*4882a593Smuzhiyun * @release: pointer to the function that will release the resources allocated
45*4882a593Smuzhiyun * by the @open function.
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun struct media_file_operations {
48*4882a593Smuzhiyun struct module *owner;
49*4882a593Smuzhiyun ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
50*4882a593Smuzhiyun ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
51*4882a593Smuzhiyun __poll_t (*poll) (struct file *, struct poll_table_struct *);
52*4882a593Smuzhiyun long (*ioctl) (struct file *, unsigned int, unsigned long);
53*4882a593Smuzhiyun long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
54*4882a593Smuzhiyun int (*open) (struct file *);
55*4882a593Smuzhiyun int (*release) (struct file *);
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /**
59*4882a593Smuzhiyun * struct media_devnode - Media device node
60*4882a593Smuzhiyun * @media_dev: pointer to struct &media_device
61*4882a593Smuzhiyun * @fops: pointer to struct &media_file_operations with media device ops
62*4882a593Smuzhiyun * @dev: pointer to struct &device containing the media controller device
63*4882a593Smuzhiyun * @cdev: struct cdev pointer character device
64*4882a593Smuzhiyun * @parent: parent device
65*4882a593Smuzhiyun * @minor: device node minor number
66*4882a593Smuzhiyun * @flags: flags, combination of the ``MEDIA_FLAG_*`` constants
67*4882a593Smuzhiyun * @release: release callback called at the end of ``media_devnode_release()``
68*4882a593Smuzhiyun * routine at media-device.c.
69*4882a593Smuzhiyun *
70*4882a593Smuzhiyun * This structure represents a media-related device node.
71*4882a593Smuzhiyun *
72*4882a593Smuzhiyun * The @parent is a physical device. It must be set by core or device drivers
73*4882a593Smuzhiyun * before registering the node.
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun struct media_devnode {
76*4882a593Smuzhiyun struct media_device *media_dev;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* device ops */
79*4882a593Smuzhiyun const struct media_file_operations *fops;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /* sysfs */
82*4882a593Smuzhiyun struct device dev; /* media device */
83*4882a593Smuzhiyun struct cdev cdev; /* character device */
84*4882a593Smuzhiyun struct device *parent; /* device parent */
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* device info */
87*4882a593Smuzhiyun int minor;
88*4882a593Smuzhiyun unsigned long flags; /* Use bitops to access flags */
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* callbacks */
91*4882a593Smuzhiyun void (*release)(struct media_devnode *devnode);
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /* dev to media_devnode */
95*4882a593Smuzhiyun #define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /**
98*4882a593Smuzhiyun * media_devnode_register - register a media device node
99*4882a593Smuzhiyun *
100*4882a593Smuzhiyun * @mdev: struct media_device we want to register a device node
101*4882a593Smuzhiyun * @devnode: media device node structure we want to register
102*4882a593Smuzhiyun * @owner: should be filled with %THIS_MODULE
103*4882a593Smuzhiyun *
104*4882a593Smuzhiyun * The registration code assigns minor numbers and registers the new device node
105*4882a593Smuzhiyun * with the kernel. An error is returned if no free minor number can be found,
106*4882a593Smuzhiyun * or if the registration of the device node fails.
107*4882a593Smuzhiyun *
108*4882a593Smuzhiyun * Zero is returned on success.
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * Note that if the media_devnode_register call fails, the release() callback of
111*4882a593Smuzhiyun * the media_devnode structure is *not* called, so the caller is responsible for
112*4882a593Smuzhiyun * freeing any data.
113*4882a593Smuzhiyun */
114*4882a593Smuzhiyun int __must_check media_devnode_register(struct media_device *mdev,
115*4882a593Smuzhiyun struct media_devnode *devnode,
116*4882a593Smuzhiyun struct module *owner);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /**
119*4882a593Smuzhiyun * media_devnode_unregister_prepare - clear the media device node register bit
120*4882a593Smuzhiyun * @devnode: the device node to prepare for unregister
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun * This clears the passed device register bit. Future open calls will be met
123*4882a593Smuzhiyun * with errors. Should be called before media_devnode_unregister() to avoid
124*4882a593Smuzhiyun * races with unregister and device file open calls.
125*4882a593Smuzhiyun *
126*4882a593Smuzhiyun * This function can safely be called if the device node has never been
127*4882a593Smuzhiyun * registered or has already been unregistered.
128*4882a593Smuzhiyun */
129*4882a593Smuzhiyun void media_devnode_unregister_prepare(struct media_devnode *devnode);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /**
132*4882a593Smuzhiyun * media_devnode_unregister - unregister a media device node
133*4882a593Smuzhiyun * @devnode: the device node to unregister
134*4882a593Smuzhiyun *
135*4882a593Smuzhiyun * This unregisters the passed device. Future open calls will be met with
136*4882a593Smuzhiyun * errors.
137*4882a593Smuzhiyun *
138*4882a593Smuzhiyun * Should be called after media_devnode_unregister_prepare()
139*4882a593Smuzhiyun */
140*4882a593Smuzhiyun void media_devnode_unregister(struct media_devnode *devnode);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /**
143*4882a593Smuzhiyun * media_devnode_data - returns a pointer to the &media_devnode
144*4882a593Smuzhiyun *
145*4882a593Smuzhiyun * @filp: pointer to struct &file
146*4882a593Smuzhiyun */
media_devnode_data(struct file * filp)147*4882a593Smuzhiyun static inline struct media_devnode *media_devnode_data(struct file *filp)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun return filp->private_data;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /**
153*4882a593Smuzhiyun * media_devnode_is_registered - returns true if &media_devnode is registered;
154*4882a593Smuzhiyun * false otherwise.
155*4882a593Smuzhiyun *
156*4882a593Smuzhiyun * @devnode: pointer to struct &media_devnode.
157*4882a593Smuzhiyun *
158*4882a593Smuzhiyun * Note: If mdev is NULL, it also returns false.
159*4882a593Smuzhiyun */
media_devnode_is_registered(struct media_devnode * devnode)160*4882a593Smuzhiyun static inline int media_devnode_is_registered(struct media_devnode *devnode)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun if (!devnode)
163*4882a593Smuzhiyun return false;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun #endif /* _MEDIA_DEVNODE_H */
169