[PATCH v8 06/12] media: Media device information query

Laurent Pinchart
2011-01-27T12:30:48Z

Create the following ioctl and implement it at the media device level to
query device information.

- MEDIA_IOC_DEVICE_INFO: Query media device information

The ioctl and its data structure are defined in the new kernel header
linux/media.h available to userspace applications.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
Documentation/DocBook/media-entities.tmpl | 12 ++
Documentation/DocBook/v4l/media-controller.xml | 10 ++
Documentation/DocBook/v4l/media-func-close.xml | 59 +++++++++
Documentation/DocBook/v4l/media-func-ioctl.xml | 116 +++++++++++++++++
Documentation/DocBook/v4l/media-func-open.xml | 94 ++++++++++++++
.../DocBook/v4l/media-ioc-device-info.xml | 132 ++++++++++++++++++++
drivers/media/media-device.c | 57 +++++++++
include/linux/Kbuild | 1 +
include/linux/media.h | 45 +++++++
9 files changed, 526 insertions(+), 0 deletions(-)
create mode 100644 Documentation/DocBook/v4l/media-func-close.xml
create mode 100644 Documentation/DocBook/v4l/media-func-ioctl.xml
create mode 100644 Documentation/DocBook/v4l/media-func-open.xml
create mode 100644 Documentation/DocBook/v4l/media-ioc-device-info.xml
create mode 100644 include/linux/media.h

diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index 61d6f11..6af3375 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -11,6 +11,10 @@
<!ENTITY func-select " <function>select()</function> ">
<!ENTITY func-write " <function>write()</function> ">

+<!ENTITY media-func-close " <function>close()</function> ">
+<!ENTITY media-func-ioctl " <function>ioctl()</function> ">
+<!ENTITY media-func-open " <function>open()</function> ">
+

<!ENTITY VIDIOC-CROPCAP " <constant>VIDIOC_CROPCAP</constant> ">
<!ENTITY VIDIOC-DBG-G-CHIP-IDENT " <constant>VIDIOC_DBG_G_CHIP_IDENT</constant> ">
@@ -87,6 +91,8 @@
<!ENTITY VIDIOC-TRY-FMT " <constant>VIDIOC_TRY_FMT</constant> ">
<!ENTITY VIDIOC-UNSUBSCRIBE-EVENT " <constant>VIDIOC_UNSUBSCRIBE_EVENT</constant> ">

+<!ENTITY MEDIA-IOC-DEVICE-INFO " <constant>MEDIA_IOC_DEVICE_INFO</constant> ">
+

<!ENTITY v4l2-std-id " v4l2_std_id ">

@@ -181,6 +187,8 @@
<!ENTITY v4l2-vbi-format "struct v4l2_vbi_format ">
<!ENTITY v4l2-window "struct v4l2_window ">

+<!ENTITY media-device-info "struct media_device_info ">
+

<!ENTITY EACCES "<errorcode>EACCES</errorcode> error code">
<!ENTITY EAGAIN "<errorcode>EAGAIN</errorcode> error code">
@@ -322,6 +330,10 @@
<!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">

<!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
+<!ENTITY sub-media-open SYSTEM "v4l/media-func-open.xml">
+<!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml">
+<!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml">
+<!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">


<!ENTITY close SYSTEM "v4l/func-close.xml">
diff --git a/Documentation/DocBook/v4l/media-controller.xml b/Documentation/DocBook/v4l/media-controller.xml
index f89228d..a46b786 100644
--- a/Documentation/DocBook/v4l/media-controller.xml
+++ b/Documentation/DocBook/v4l/media-controller.xml
@@ -74,3 +74,13 @@
pad to a sink pad.

</chapter>
+
+<appendix id="media-user-func">
+ Function Reference
+
+ &sub-media-open;
+ &sub-media-close;
+ &sub-media-ioctl;
+
+ &sub-media-ioc-device-info;
+</appendix>
diff --git a/Documentation/DocBook/v4l/media-func-close.xml b/Documentation/DocBook/v4l/media-func-close.xml
new file mode 100644
index 0000000..be149c8
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-func-close.xml
@@ -0,0 +1,59 @@
+<refentry id="media-func-close">
+ <refmeta>
+ <refentrytitle>media close()</refentrytitle>
+ &manvol;
+ </refmeta>
+
+ <refnamediv>
+ <refname>media-close</refname>
+ <refpurpose>Close a media device</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>int <function>close</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ Arguments
+
+ <variablelist>
+ <varlistentry>
+ <term><parameter>fd</parameter></term>
+
+ &fd;
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ Description
+
+ Closes the media device. Resources associated with the file descriptor
+ are freed. The device configuration remain unchanged.
+ </refsect1>
+
+ <refsect1>
+ Return Value
+
+ <function>close</function> returns 0 on success. On error, -1 is
+ returned, and <varname>errno</varname> is set appropriately. Possible error
+ codes are:
+
+ <variablelist>
+ <varlistentry>
+ <term><errorcode>EBADF</errorcode></term>
+
+ <parameter>fd</parameter> is not a valid open file descriptor.
+
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/v4l/media-func-ioctl.xml b/Documentation/DocBook/v4l/media-func-ioctl.xml
new file mode 100644
index 0000000..bda8604
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-func-ioctl.xml
@@ -0,0 +1,116 @@
+<refentry id="media-func-ioctl">
+ <refmeta>
+ <refentrytitle>media ioctl()</refentrytitle>
+ &manvol;
+ </refmeta>
+
+ <refnamediv>
+ <refname>media-ioctl</refname>
+ <refpurpose>Control a media device</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;sys/ioctl.h&gt;</funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>int <function>ioctl</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>int <parameter>request</parameter></paramdef>
+ <paramdef>void *<parameter>argp</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ Arguments
+
+ <variablelist>
+ <varlistentry>
+ <term><parameter>fd</parameter></term>
+
+ &fd;
+
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>request</parameter></term>
+
+ Media ioctl request code as defined in the media.h header file,
+ for example MEDIA_IOC_SETUP_LINK.
+
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>argp</parameter></term>
+
+ Pointer to a request-specific structure.
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ Description
+ The <function>ioctl()</function> function manipulates media device
+ parameters. The argument <parameter>fd</parameter> must be an open file
+ descriptor.
+ The ioctl <parameter>request</parameter> code specifies the media
+ function to be called. It has encoded in it whether the argument is an
+ input, output or read/write parameter, and the size of the argument
+ <parameter>argp</parameter> in bytes.
+ Macros and structures definitions specifying media ioctl requests and
+ their parameters are located in the media.h header file. All media ioctl
+ requests, their respective function and parameters are specified in
+ .
+ </refsect1>
+
+ <refsect1>
+ Return Value
+
+ <function>ioctl()</function> returns <returnvalue>0</returnvalue> on
+ success. On failure, <returnvalue>-1</returnvalue> is returned, and the
+ <varname>errno</varname> variable is set appropriately. Generic error codes
+ are listed below, and request-specific error codes are listed in the
+ individual requests descriptions.
+ When an ioctl that takes an output or read/write parameter fails,
+ the parameter remains unmodified.
+
+ <variablelist>
+ <varlistentry>
+ <term><errorcode>EBADF</errorcode></term>
+
+ <parameter>fd</parameter> is not a valid open file descriptor.
+
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EFAULT</errorcode></term>
+
+ <parameter>argp</parameter> references an inaccessible memory
+ area.
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EINVAL</errorcode></term>
+
+ The <parameter>request</parameter> or the data pointed to by
+ <parameter>argp</parameter> is not valid. This is a very common error
+ code, see the individual ioctl requests listed in
+ for actual causes.
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>ENOMEM</errorcode></term>
+
+ Insufficient kernel memory was available to complete the
+ request.
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>ENOTTY</errorcode></term>
+
+ <parameter>fd</parameter> is not associated with a character
+ special device.
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/v4l/media-func-open.xml b/Documentation/DocBook/v4l/media-func-open.xml
new file mode 100644
index 0000000..f7df034
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-func-open.xml
@@ -0,0 +1,94 @@
+<refentry id="media-func-open">
+ <refmeta>
+ <refentrytitle>media open()</refentrytitle>
+ &manvol;
+ </refmeta>
+
+ <refnamediv>
+ <refname>media-open</refname>
+ <refpurpose>Open a media device</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
+ <funcprototype>
+ <funcdef>int <function>open</function></funcdef>
+ <paramdef>const char *<parameter>device_name</parameter></paramdef>
+ <paramdef>int <parameter>flags</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ Arguments
+
+ <variablelist>
+ <varlistentry>
+ <term><parameter>device_name</parameter></term>
+
+ Device to be opened.
+
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>flags</parameter></term>
+
+ Open flags. Access mode must be either <constant>O_RDONLY</constant>
+ or <constant>O_RDWR</constant>. Other flags have no effect.
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ Description
+ To open a media device applications call <function>open()</function>
+ with the desired device name. The function has no side effects; the device
+ configuration remain unchanged.
+ When the device is opened in read-only mode, attemps to modify its
+ configuration will result in an error, and <varname>errno</varname> will be
+ set to <errorcode>EBADF</errorcode>.
+ </refsect1>
+ <refsect1>
+ Return Value
+
+ <function>open</function> returns the new file descriptor on success.
+ On error, -1 is returned, and <varname>errno</varname> is set appropriately.
+ Possible error codes are:
+
+ <variablelist>
+ <varlistentry>
+ <term><errorcode>EACCES</errorcode></term>
+
+ The requested access to the file is not allowed.
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EMFILE</errorcode></term>
+
+ The process already has the maximum number of files open.
+
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>ENFILE</errorcode></term>
+
+ The system limit on the total number of open files has been
+ reached.
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>ENOMEM</errorcode></term>
+
+ Insufficient kernel memory was available.
+
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>ENXIO</errorcode></term>
+
+ No device corresponding to this device special file exists.
+
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/v4l/media-ioc-device-info.xml b/Documentation/DocBook/v4l/media-ioc-device-info.xml
new file mode 100644
index 0000000..278a312
--- /dev/null
+++ b/Documentation/DocBook/v4l/media-ioc-device-info.xml
@@ -0,0 +1,132 @@
+<refentry id="media-ioc-device-info">
+ <refmeta>
+ <refentrytitle>ioctl MEDIA_IOC_DEVICE_INFO</refentrytitle>
+ &manvol;
+ </refmeta>
+
+ <refnamediv>
+ <refname>MEDIA_IOC_DEVICE_INFO</refname>
+ <refpurpose>Query device information</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcprototype>
+ <funcdef>int <function>ioctl</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>int <parameter>request</parameter></paramdef>
+ <paramdef>struct media_device_info *<parameter>argp</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ Arguments
+
+ <variablelist>
+ <varlistentry>
+ <term><parameter>fd</parameter></term>
+
+ &fd;
+
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>request</parameter></term>
+
+ MEDIA_IOC_DEVICE_INFO
+
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>argp</parameter></term>
+
+
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ Description
+
+ All media devices must support the <constant>MEDIA_IOC_DEVICE_INFO</constant>
+ ioctl. To query device information, applications call the ioctl with a
+ pointer to a &media-device-info;. The driver fills the structure and returns
+ the information to the application.
+ The ioctl never fails.
+
+
+ struct <structname>media_device_info</structname>
+ <tgroup cols="3">
+ &cs-str;
+
+ <row>
+ <entry>char</entry>
+ <entry><structfield>driver</structfield>[16]</entry>
+ <entry> Name of the driver implementing the media API as a
+ NUL-terminated ASCII string. The driver version is stored in the
+ <structfield>driver_version</structfield> field.
+ Driver specific applications can use this information to
+ verify the driver identity. It is also useful to work around
+ known bugs, or to identify drivers in error reports. </entry>
+ </row>
+ <row>
+ <entry>char</entry>
+ <entry><structfield>model</structfield>[32]</entry>
+ <entry>Device model name as a NUL-terminated UTF-8 string. The
+ device version is stored in the <structfield>device_version</structfield>
+ field and is not be appended to the model name.</entry>
+ </row>
+ <row>
+ <entry>char</entry>
+ <entry><structfield>serial</structfield>[40]</entry>
+ <entry>Serial number as a NUL-terminated ASCII string.</entry>
+ </row>
+ <row>
+ <entry>char</entry>
+ <entry><structfield>bus_info</structfield>[32]</entry>
+ <entry>Location of the device in the system as a NUL-terminated
+ ASCII string. This includes the bus type name (PCI, USB, ...) and a
+ bus-specific identifier.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>media_version</structfield></entry>
+ <entry>Media API version, formatted with the
+ <constant>KERNEL_VERSION()</constant> macro.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>hw_revision</structfield></entry>
+ <entry>Hardware device revision in a driver-specific format.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>media_version</structfield></entry>
+ <entry>Media device driver version, formatted with the
+ <constant>KERNEL_VERSION()</constant> macro. Together with the
+ <structfield>driver</structfield> field this identifies a particular
+ driver.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>reserved</structfield>[31]</entry>
+ <entry>Reserved for future extensions. Drivers and applications must
+ set this array to zero.</entry>
+ </row>
+
+ </tgroup>
+
+ The <structfield>serial</structfield> and <structfield>bus_info</structfield>
+ fields can be used to distinguish between multiple instances of otherwise
+ identical hardware. The serial number takes precedence when provided and can
+ be assumed to be unique. If the serial number is an empty string, the
+ <structfield>bus_info</structfield> field can be used instead. The
+ <structfield>bus_info</structfield> field is guaranteed to be unique, but
+ can vary across reboots or device unplug/replug.
+ </refsect1>
+
+ <refsect1>
+ Return value
+ This function doesn't return specific error codes.
+ </refsect1>
+</refentry>
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index e4c2157..5c745be 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -22,13 +22,70 @@

#include <linux/types.h>
#include <linux/ioctl.h>
+#include <linux/media.h>

#include <media/media-device.h>
#include <media/media-devnode.h>
#include <media/media-entity.h>

+/* -----------------------------------------------------------------------------
+ * Userspace API
+ */
+
+static int media_device_open(struct file *filp)
+{
+ return 0;
+}
+
+static int media_device_close(struct file *filp)
+{
+ return 0;
+}
+
+static int media_device_get_info(struct media_device *dev,
+ struct media_device_info __user *__info)
+{
+ struct media_device_info info;
+
+ memset(&info, 0, sizeof(info));
+
+ strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver));
+ strlcpy(info.model, dev->model, sizeof(info.model));
+ strlcpy(info.serial, dev->serial, sizeof(info.serial));
+ strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info));
+
+ info.media_version = MEDIA_API_VERSION;
+ info.hw_revision = dev->hw_revision;
+ info.driver_version = dev->driver_version;
+
+ return copy_to_user(__info, &info, sizeof(*__info));
+}
+
+static long media_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct media_devnode *devnode = media_devnode_data(filp);
+ struct media_device *dev = to_media_device(devnode);
+ long ret;
+
+ switch (cmd) {
+ case MEDIA_IOC_DEVICE_INFO:
+ ret = media_device_get_info(dev,
+ (struct media_device_info __user *)arg);
+ break;
+
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+
+ return ret;
+}
+
static const struct media_file_operations media_device_fops = {
.owner = THIS_MODULE,
+ .open = media_device_open,
+ .ioctl = media_device_ioctl,
+ .release = media_device_close,
};

/* -----------------------------------------------------------------------------
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 97319a8..26e0a7f 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -228,6 +228,7 @@ header-y += magic.h
header-y += major.h
header-y += map_to_7segment.h
header-y += matroxfb.h
+header-y += media.h
header-y += mempolicy.h
header-y += meye.h
header-y += mii.h
diff --git a/include/linux/media.h b/include/linux/media.h
new file mode 100644
index 0000000..4c52f08
--- /dev/null
+++ b/include/linux/media.h
@@ -0,0 +1,45 @@
+/*
+ * Multimedia device API
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LINUX_MEDIA_H
+#define __LINUX_MEDIA_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#define MEDIA_API_VERSION KERNEL_VERSION(0, 1, 0)
+
+struct media_device_info {
+ char driver[16];
+ char model[32];
+ char serial[40];
+ char bus_info[32];
+ __u32 media_version;
+ __u32 hw_revision;
+ __u32 driver_version;
+ __u32 reserved[31];
+};
+
+#define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info)
+
+#endif /* __LINUX_MEDIA_H */
--
1.7.3.4