summaryrefslogtreecommitdiff
path: root/include/media/media-devnode.h
blob: d27c1c646c2805171be3997d72210dd4d1a38e32 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Media device node
 *
 * Copyright (C) 2010 Nokia Corporation
 *
 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 *	     Sakari Ailus <sakari.ailus@iki.fi>
 *
 * --
 *
 * Common functions for media-related drivers to register and unregister media
 * device nodes.
 */

#ifndef _MEDIA_DEVNODE_H
#define _MEDIA_DEVNODE_H

#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>

struct media_device;

/*
 * Flag to mark the media_devnode struct as registered. Drivers must not touch
 * this flag directly, it will be set and cleared by media_devnode_register and
 * media_devnode_unregister.
 */
#define MEDIA_FLAG_REGISTERED	0

/**
 * struct media_file_operations - Media device file operations
 *
 * @owner: should be filled with %THIS_MODULE
 * @read: pointer to the function that implements read() syscall
 * @write: pointer to the function that implements write() syscall
 * @poll: pointer to the function that implements poll() syscall
 * @ioctl: pointer to the function that implements ioctl() syscall
 * @compat_ioctl: pointer to the function that will handle 32 bits userspace
 *	calls to the ioctl() syscall on a Kernel compiled with 64 bits.
 * @open: pointer to the function that implements open() syscall
 * @release: pointer to the function that will release the resources allocated
 *	by the @open function.
 */
struct media_file_operations {
	struct module *owner;
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	__poll_t (*poll) (struct file *, struct poll_table_struct *);
	long (*ioctl) (struct file *, unsigned int, unsigned long);
	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
	int (*open) (struct file *);
	int (*release) (struct file *);
};

/**
 * struct media_devnode - Media device node
 * @media_dev:	pointer to struct &media_device
 * @fops:	pointer to struct &media_file_operations with media device ops
 * @dev:	pointer to struct &device containing the media controller device
 * @cdev:	struct cdev pointer character device
 * @parent:	parent device
 * @minor:	device node minor number
 * @flags:	flags, combination of the ``MEDIA_FLAG_*`` constants
 * @release:	release callback called at the end of ``media_devnode_release()``
 *		routine at media-device.c.
 *
 * This structure represents a media-related device node.
 *
 * The @parent is a physical device. It must be set by core or device drivers
 * before registering the node.
 */
struct media_devnode {
	struct media_device *media_dev;

	/* device ops */
	const struct media_file_operations *fops;

	/* sysfs */
	struct device dev;		/* media device */
	struct cdev cdev;		/* character device */
	struct device *parent;		/* device parent */

	/* device info */
	int minor;
	unsigned long flags;		/* Use bitops to access flags */

	/* callbacks */
	void (*release)(struct media_devnode *devnode);
};

/* dev to media_devnode */
#define to_media_devnode(cd) container_of(cd, struct media_devnode, dev)

/**
 * media_devnode_register - register a media device node
 *
 * @mdev: struct media_device we want to register a device node
 * @devnode: media device node structure we want to register
 * @owner: should be filled with %THIS_MODULE
 *
 * The registration code assigns minor numbers and registers the new device node
 * with the kernel. An error is returned if no free minor number can be found,
 * or if the registration of the device node fails.
 *
 * Zero is returned on success.
 *
 * Note that if the media_devnode_register call fails, the release() callback of
 * the media_devnode structure is *not* called, so the caller is responsible for
 * freeing any data.
 */
int __must_check media_devnode_register(struct media_device *mdev,
					struct media_devnode *devnode,
					struct module *owner);

/**
 * media_devnode_unregister_prepare - clear the media device node register bit
 * @devnode: the device node to prepare for unregister
 *
 * This clears the passed device register bit. Future open calls will be met
 * with errors. Should be called before media_devnode_unregister() to avoid
 * races with unregister and device file open calls.
 *
 * This function can safely be called if the device node has never been
 * registered or has already been unregistered.
 */
void media_devnode_unregister_prepare(struct media_devnode *devnode);

/**
 * media_devnode_unregister - unregister a media device node
 * @devnode: the device node to unregister
 *
 * This unregisters the passed device. Future open calls will be met with
 * errors.
 *
 * Should be called after media_devnode_unregister_prepare()
 */
void media_devnode_unregister(struct media_devnode *devnode);

/**
 * media_devnode_data - returns a pointer to the &media_devnode
 *
 * @filp: pointer to struct &file
 */
static inline struct media_devnode *media_devnode_data(struct file *filp)
{
	return filp->private_data;
}

/**
 * media_devnode_is_registered - returns true if &media_devnode is registered;
 *	false otherwise.
 *
 * @devnode: pointer to struct &media_devnode.
 *
 * Note: If mdev is NULL, it also returns false.
 */
static inline int media_devnode_is_registered(struct media_devnode *devnode)
{
	if (!devnode)
		return false;

	return test_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
}

#endif /* _MEDIA_DEVNODE_H */