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