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@xxxxxxxxxxxxxxxx> --- Documentation/media-framework.txt | 42 +++++++++++++++++++++++++++ drivers/media/media-device.c | 57 +++++++++++++++++++++++++++++++++++++ include/linux/media.h | 23 +++++++++++++++ include/media/media-device.h | 3 ++ 4 files changed, 125 insertions(+), 0 deletions(-) create mode 100644 include/linux/media.h diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index 59649e9..66f7f6c 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -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. diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index c309d3c..1415ebd 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -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, }; /* ----------------------------------------------------------------------------- diff --git a/include/linux/media.h b/include/linux/media.h new file mode 100644 index 0000000..bca08a7 --- /dev/null +++ b/include/linux/media.h @@ -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 */ diff --git a/include/media/media-device.h b/include/media/media-device.h index 3c9a5e0..6f57f41 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.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); -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html