@@ -315,3 +315,45 @@ required, drivers don't need to provide a set_power operation. The operation
is allowed to fail when turning power on, in which case the media_entity_get
function will return NULL.
+
+Userspace application API
+-------------------------
+
+Media devices offer an API to userspace application to query device information
+through ioctls.
+
+ MEDIA_IOC_DEVICE_INFO - Get device information
+ ----------------------------------------------
+
+ ioctl(int fd, int request, struct media_device_info *argp);
+
+To query device information, call the MEDIA_IOC_ENUM_ENTITIES ioctl with a
+pointer to a media_device_info structure. The driver fills the structure and
+returns the information to the application. The ioctl never fails.
+
+The media_device_info structure is defined as
+
+- struct media_device_info
+
+__u8 driver[16] Driver name as a NUL-terminated ASCII string. The
+ driver version is stored in the driver_version field.
+__u8 model[32] Device model name as a NUL-terminated UTF-8 string. The
+ device version is stored in the device_version field and
+ is not be appended to the model name.
+__u8 serial[32] Serial number as an ASCII string. The string is
+ NUL-terminated unless the serial number is exactly 32
+ characters long.
+__u8 bus_info[32] 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.
+__u32 media_version Media API version, formatted with the KERNEL_VERSION
+ macro.
+__u32 device_version Media device driver version in a driver-specific format.
+__u32 driver_version Media device driver version, formatted with the
+ KERNEL_VERSION macro.
+
+The serial and bus_info 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 bus_info field can be used instead. The bus_info field is
+guaranteed to be unique, but can vary across reboots or device unplug/replug.
@@ -20,13 +20,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));
+ strncpy(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.device_version = dev->device_version;
+ 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,
+ .unlocked_ioctl = media_device_ioctl,
+ .release = media_device_close,
};
/* -----------------------------------------------------------------------------
new file mode 100644
@@ -0,0 +1,23 @@
+#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 {
+ __u8 driver[16];
+ __u8 model[32];
+ __u8 serial[32];
+ __u8 bus_info[32];
+ __u32 media_version;
+ __u32 device_version;
+ __u32 driver_version;
+ __u32 reserved[5];
+};
+
+#define MEDIA_IOC_DEVICE_INFO _IOWR('M', 1, struct media_device_info)
+
+#endif /* __LINUX_MEDIA_H */
@@ -73,6 +73,9 @@ struct media_device {
struct mutex graph_mutex;
};
+/* media_devnode to media_device */
+#define to_media_device(node) container_of(node, struct media_device, devnode)
+
int __must_check media_device_register(struct media_device *mdev);
void media_device_unregister(struct media_device *mdev);