From 2bb0cfbf8137e02cc32aae3b36f85ef7300e8936 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 9 Jun 2018 14:29:41 +0300 Subject: Split UVC gadget into a library and test application Split the project into a UVC gadget library and a test application. To avoid rolling out a custom build system, switch to CMake. Signed-off-by: Laurent Pinchart --- include/uvcgadget/configfs.h | 108 +++++++++++++++++++++++++++++++++++++ include/uvcgadget/events.h | 49 +++++++++++++++++ include/uvcgadget/list.h | 95 ++++++++++++++++++++++++++++++++ include/uvcgadget/stream.h | 113 +++++++++++++++++++++++++++++++++++++++ include/uvcgadget/v4l2-source.h | 20 +++++++ include/uvcgadget/video-source.h | 55 +++++++++++++++++++ 6 files changed, 440 insertions(+) create mode 100644 include/uvcgadget/configfs.h create mode 100644 include/uvcgadget/events.h create mode 100644 include/uvcgadget/list.h create mode 100644 include/uvcgadget/stream.h create mode 100644 include/uvcgadget/v4l2-source.h create mode 100644 include/uvcgadget/video-source.h (limited to 'include/uvcgadget') diff --git a/include/uvcgadget/configfs.h b/include/uvcgadget/configfs.h new file mode 100644 index 0000000..e5a7efa --- /dev/null +++ b/include/uvcgadget/configfs.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * ConfigFS Gadget device handling + * + * Copyright (C) 2018 Kieran Bingham + * + * Contact: Kieran Bingham + */ + +#ifndef __CONFIGFS_H__ +#define __CONFIGFS_H__ + +#include + +/* + * struct uvc_function_config_endpoint - Endpoint parameters + * @bInterval: Transfer interval (interrupt and isochronous only) + * @bMaxBurst: Transfer burst size (super-speed only) + * @wMaxPacketSize: Maximum packet size (including the multiplier) + */ +struct uvc_function_config_endpoint { + unsigned int bInterval; + unsigned int bMaxBurst; + unsigned int wMaxPacketSize; +}; + +/* + * struct uvc_function_config_interface - Interface parameters + * @bInterfaceNumber: Interface number + */ +struct uvc_function_config_interface { + unsigned int bInterfaceNumber; +}; + +/* + * struct uvc_function_config_control - Control interface parameters + * @intf: Generic interface parameters + */ +struct uvc_function_config_control { + struct uvc_function_config_interface intf; +}; + +/* + * struct uvc_function_config_frame - Streaming frame parameters + * @index: Frame index in the UVC descriptors + * @width: Frame width in pixels + * @height: Frame height in pixels + * @num_intervals: Number of entries in the intervals array + * @intervals: Array of frame intervals + */ +struct uvc_function_config_frame { + unsigned int index; + unsigned int width; + unsigned int height; + unsigned int num_intervals; + unsigned int *intervals; +}; + +/* + * struct uvc_function_config_format - Streaming format parameters + * @index: Format index in the UVC descriptors + * @guid: Format GUID + * @fcc: V4L2 pixel format + * @num_frames: Number of entries in the frames array + * @frames: Array of frame descriptors + */ +struct uvc_function_config_format { + unsigned int index; + uint8_t guid[16]; + unsigned int fcc; + unsigned int num_frames; + struct uvc_function_config_frame *frames; +}; + +/* + * struct uvc_function_config_streaming - Streaming interface parameters + * @intf: Generic interface parameters + * @ep: Endpoint parameters + * @num_formats: Number of entries in the formats array + * @formats: Array of format descriptors + */ +struct uvc_function_config_streaming { + struct uvc_function_config_interface intf; + struct uvc_function_config_endpoint ep; + + unsigned int num_formats; + struct uvc_function_config_format *formats; +}; + +/* + * struct uvc_function_config - UVC function configuration parameters + * @video: Full path to the video device node + * @udc: UDC name + * @control: Control interface configuration + * @streaming: Streaming interface configuration + */ +struct uvc_function_config { + char *video; + char *udc; + + struct uvc_function_config_control control; + struct uvc_function_config_streaming streaming; +}; + +struct uvc_function_config *configfs_parse_uvc_function(const char *function); +void configfs_free_uvc_function(struct uvc_function_config *fc); + +#endif diff --git a/include/uvcgadget/events.h b/include/uvcgadget/events.h new file mode 100644 index 0000000..b0b8fa8 --- /dev/null +++ b/include/uvcgadget/events.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Generic Event Handling + * + * Copyright (C) 2018 Laurent Pinchart + * + * This file comes from the omap3-isp-live project + * (git://git.ideasonboard.org/omap3-isp-live.git) + * + * Copyright (C) 2010-2011 Ideas on board SPRL + * + * Contact: Laurent Pinchart + */ + +#ifndef __EVENTS_H__ +#define __EVENTS_H__ + +#include +#include + +#include "list.h" + +struct events { + struct list_entry events; + bool done; + + int maxfd; + fd_set rfds; + fd_set wfds; + fd_set efds; +}; + +enum event_type { + EVENT_READ = 1, + EVENT_WRITE = 2, + EVENT_EXCEPTION = 4, +}; + +void events_watch_fd(struct events *events, int fd, enum event_type type, + void(*callback)(void *), void *priv); +void events_unwatch_fd(struct events *events, int fd, enum event_type type); + +bool events_loop(struct events *events); +void events_stop(struct events *events); + +void events_init(struct events *events); +void events_cleanup(struct events *events); + +#endif diff --git a/include/uvcgadget/list.h b/include/uvcgadget/list.h new file mode 100644 index 0000000..8854c6e --- /dev/null +++ b/include/uvcgadget/list.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Double Linked Lists + * + * Copyright (C) 2018 Laurent Pinchart + * + * This file comes from the omap3-isp-live project + * (git://git.ideasonboard.org/omap3-isp-live.git) + * + * Copyright (C) 2010-2011 Ideas on board SPRL + * + * Contact: Laurent Pinchart + */ + +#ifndef __LIST_H +#define __LIST_H + +#include + +struct list_entry { + struct list_entry *prev; + struct list_entry *next; +}; + +static inline void list_init(struct list_entry *list) +{ + list->next = list; + list->prev = list; +} + +static inline int list_empty(struct list_entry *list) +{ + return list->next == list; +} + +static inline void list_append(struct list_entry *entry, struct list_entry *list) +{ + entry->next = list; + entry->prev = list->prev; + list->prev->next = entry; + list->prev = entry; +} + +static inline void list_prepend(struct list_entry *entry, struct list_entry *list) +{ + entry->next = list->next; + entry->prev = list; + list->next->prev = entry; + list->next = entry; +} + +static inline void list_insert_after(struct list_entry *entry, struct list_entry *after) +{ + list_prepend(entry, after); +} + +static inline void list_insert_before(struct list_entry *entry, struct list_entry *before) +{ + list_append(entry, before); +} + +static inline void list_remove(struct list_entry *entry) +{ + entry->prev->next = entry->next; + entry->next->prev = entry->prev; +} + +#define list_entry(entry, type, member) \ + (type *)((char *)(entry) - offsetof(type, member)) + +#define list_first_entry(list, type, member) \ + list_entry((list)->next, type, member) + +#define list_last_entry(list, type, member) \ + list_entry((list)->prev, type, member) + +#define list_for_each(entry, list) \ + for (entry = (list)->next; entry != (list); entry = entry->next) + +#define list_for_each_entry(entry, list, member) \ + for (entry = list_entry((list)->next, typeof(*entry), member); \ + &entry->member != (list); \ + entry = list_entry(entry->member.next, typeof(*entry), member)) + +#define list_for_each_safe(entry, __next, list) \ + for (entry = (list)->next, __next = entry->next; entry != (list); \ + entry = __next, __next = entry->next) + +#define list_for_each_entry_safe(entry, __next, list, member) \ + for (entry = list_entry((list)->next, typeof(*entry), member), \ + __next = list_entry(entry->member.next, typeof(*entry), member); \ + &entry->member != (list); \ + entry = __next, __next = list_entry(entry->member.next, typeof(*entry), member)) + +#endif /* __LIST_H */ diff --git a/include/uvcgadget/stream.h b/include/uvcgadget/stream.h new file mode 100644 index 0000000..13779d3 --- /dev/null +++ b/include/uvcgadget/stream.h @@ -0,0 +1,113 @@ +/* + * UVC stream handling + * + * Copyright (C) 2010 Ideas on board SPRL + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., + */ + +#ifndef __STREAM_H__ +#define __STREAM_H__ + +struct events; +struct uvc_function_config; +struct uvc_stream; +struct v4l2_pix_format; +struct video_source; + +/* + * uvc_stream_new - Create a new UVC stream + * @uvc_device: Filename of UVC device node + * + * Create a new UVC stream to handle the UVC function corresponding to the video + * device node @uvc_device. + * + * Streams allocated with this function can be deleted with uvc_stream_delete(). + * + * On success, returns a pointer to newly allocated and populated struct uvc_stream. + * On failure, returns NULL. + */ +struct uvc_stream *uvc_stream_new(const char *uvc_device); + +/* + * uvc_stream_init_uvc - Initialize a UVC stream + * @stream: the UVC stream + * @fc: UVC function configuration + * + * Before it can be used, a UVC stream has to be initialized by calling this + * function with a UVC function configuration @fc. The function configuration + * contains all the parameters of the UVC function that will be handled by the + * UVC stream. It can be parsed from the UVC function ConfigFS directory using + * configfs_parse_uvc_function(). + * + * uvc_stream_init_uvc() also registers UVC event notifiers for the stream. The + * caller must have called the uvc_stream_set_event_handler() function first, + * and ensure that the event handler is immediately usable. If the event loop is + * already running, all initialization steps required to handle events must be + * fully performed before calling this function. + */ +void uvc_stream_init_uvc(struct uvc_stream *stream, + struct uvc_function_config *fc); + +/* + * uvc_stream_set_event_handler - Set an event handler for a stream + * @stream: the UVC stream + * @events: the event handler + * + * This function sets the event handler that the stream can use to be notified + * of file descriptor events. + */ +void uvc_stream_set_event_handler(struct uvc_stream *stream, + struct events *events); + +void uvc_stream_set_video_source(struct uvc_stream *stream, + struct video_source *src); + +/* + * uvc_stream_delete - Delete a UVC stream + * @stream: the UVC stream + * + * This functions deletes the @stream created with uvc_stream_new(). Upon return + * the stream object may be freed, the @stream pointer thus becomes invalid and + * the stream must not be touched anymore. + * + * Every stream allocated with uvc_stream_new() must be deleted when not needed + * anymore. + */ +void uvc_stream_delete(struct uvc_stream *stream); + +/* + * uvc_stream_set_format - Set the active video format for the stream + * @stream: the UVC stream + * @format: the video stream format + * + * This function is called from the UVC protocol handler to configure the video + * format for the @stream. It must not be called directly by applications. + * + * Returns 0 on success, or a negative error code on failure. + */ +int uvc_stream_set_format(struct uvc_stream *stream, + const struct v4l2_pix_format *format); + +/* + * uvc_stream_enable - Turn on/off video streaming for the UVC stream + * @stream: the UVC stream + * @enable: 0 to stop the stream, 1 to start it + * + * This function is called from the UVC protocol handler to start video transfer + * for the @stream. It must not be called directly by applications. + */ +void uvc_stream_enable(struct uvc_stream *stream, int enable); + +#endif /* __STREAM_H__ */ diff --git a/include/uvcgadget/v4l2-source.h b/include/uvcgadget/v4l2-source.h new file mode 100644 index 0000000..53e28d6 --- /dev/null +++ b/include/uvcgadget/v4l2-source.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * V4L2 video source + * + * Copyright (C) 2018 Laurent Pinchart + * + * Contact: Laurent Pinchart + */ +#ifndef __V4L2_VIDEO_SOURCE_H__ +#define __V4L2_VIDEO_SOURCE_H__ + +#include "video-source.h" + +struct events; +struct video_source; + +struct video_source *v4l2_video_source_create(const char *devname); +void v4l2_video_source_init(struct video_source *src, struct events *events); + +#endif /* __VIDEO_SOURCE_H__ */ diff --git a/include/uvcgadget/video-source.h b/include/uvcgadget/video-source.h new file mode 100644 index 0000000..fffcba3 --- /dev/null +++ b/include/uvcgadget/video-source.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Abstract video source + * + * Copyright (C) 2018 Laurent Pinchart + * + * Contact: Laurent Pinchart + */ +#ifndef __VIDEO_SOURCE_H__ +#define __VIDEO_SOURCE_H__ + +struct v4l2_buffer; +struct v4l2_pix_format; +struct video_buffer; +struct video_buffer_set; +struct video_source; + +struct video_source_ops { + void(*destroy)(struct video_source *src); + int(*set_format)(struct video_source *src, struct v4l2_pix_format *fmt); + int(*alloc_buffers)(struct video_source *src, unsigned int nbufs); + int(*export_buffers)(struct video_source *src, + struct video_buffer_set **buffers); + int(*free_buffers)(struct video_source *src); + int(*stream_on)(struct video_source *src); + int(*stream_off)(struct video_source *src); + int(*queue_buffer)(struct video_source *src, struct video_buffer *buf); +}; + +typedef void(*video_source_buffer_handler_t)(void *, struct video_source *, + struct video_buffer *); + +struct video_source { + const struct video_source_ops *ops; + struct events *events; + video_source_buffer_handler_t handler; + void *handler_data; +}; + +void video_source_set_buffer_handler(struct video_source *src, + video_source_buffer_handler_t handler, + void *data); +void video_source_destroy(struct video_source *src); +int video_source_set_format(struct video_source *src, + struct v4l2_pix_format *fmt); +int video_source_alloc_buffers(struct video_source *src, unsigned int nbufs); +int video_source_export_buffers(struct video_source *src, + struct video_buffer_set **buffers); +int video_source_free_buffers(struct video_source *src); +int video_source_stream_on(struct video_source *src); +int video_source_stream_off(struct video_source *src); +int video_source_queue_buffer(struct video_source *src, + struct video_buffer *buf); + +#endif /* __VIDEO_SOURCE_H__ */ -- cgit v1.2.3