Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46919a23 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Felipe Balbi
Browse files

usb: gadget: uvc: configfs support in uvc function



Add support for using the uvc function as a component of USB gadgets composed
with configfs.

Acked-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 6c25955e
Loading
Loading
Loading
Loading
+265 −0
Original line number Diff line number Diff line
What:		/config/usb-gadget/gadget/functions/uvc.name
Date:		Dec 2014
KernelVersion:	3.20
Description:	UVC function directory

		streaming_maxburst	- 0..15 (ss only)
		streaming_maxpacket	- 1..1023 (fs), 1..3072 (hs/ss)
		streaming_interval	- 1..16

What:		/config/usb-gadget/gadget/functions/uvc.name/control
Date:		Dec 2014
KernelVersion:	3.20
Description:	Control descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/class
Date:		Dec 2014
KernelVersion:	3.20
Description:	Class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/class/ss
Date:		Dec 2014
KernelVersion:	3.20
Description:	Super speed control class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/class/fs
Date:		Dec 2014
KernelVersion:	3.20
Description:	Full speed control class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal
Date:		Dec 2014
KernelVersion:	3.20
Description:	Terminal descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/output
Date:		Dec 2014
KernelVersion:	3.20
Description:	Output terminal descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/output/default
Date:		Dec 2014
KernelVersion:	3.20
Description:	Default output terminal descriptors

		All attributes read only:
		iTerminal	- index of string descriptor
		bSourceID 	- id of the terminal to which this terminal
				is connected
		bAssocTerminal	- id of the input terminal to which this output
				terminal is associated
		wTerminalType	- terminal type
		bTerminalID	- a non-zero id of this terminal

What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera
Date:		Dec 2014
KernelVersion:	3.20
Description:	Camera terminal descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera/default
Date:		Dec 2014
KernelVersion:	3.20
Description:	Default camera terminal descriptors

		All attributes read only:
		bmControls		- bitmap specifying which controls are
					supported for the video stream
		wOcularFocalLength	- the value of Locular
		wObjectiveFocalLengthMax- the value of Lmin
		wObjectiveFocalLengthMin- the value of Lmax
		iTerminal		- index of string descriptor
		bAssocTerminal		- id of the output terminal to which
					this terminal is connected
		wTerminalType		- terminal type
		bTerminalID		- a non-zero id of this terminal

What:		/config/usb-gadget/gadget/functions/uvc.name/control/processing
Date:		Dec 2014
KernelVersion:	3.20
Description:	Processing unit descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/processing/default
Date:		Dec 2014
KernelVersion:	3.20
Description:	Default processing unit descriptors

		All attributes read only:
		iProcessing	- index of string descriptor
		bmControls	- bitmap specifying which controls are
				supported for the video stream
		wMaxMultiplier	- maximum digital magnification x100
		bSourceID	- id of the terminal to which this unit is
				connected
		bUnitID		- a non-zero id of this unit

What:		/config/usb-gadget/gadget/functions/uvc.name/control/header
Date:		Dec 2014
KernelVersion:	3.20
Description:	Control header descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/control/header/name
Date:		Dec 2014
KernelVersion:	3.20
Description:	Specific control header descriptors

dwClockFrequency
bcdUVC
What:		/config/usb-gadget/gadget/functions/uvc.name/streaming
Date:		Dec 2014
KernelVersion:	3.20
Description:	Streaming descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class
Date:		Dec 2014
KernelVersion:	3.20
Description:	Streaming class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class/ss
Date:		Dec 2014
KernelVersion:	3.20
Description:	Super speed streaming class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class/hs
Date:		Dec 2014
KernelVersion:	3.20
Description:	High speed streaming class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class/fs
Date:		Dec 2014
KernelVersion:	3.20
Description:	Full speed streaming class descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching
Date:		Dec 2014
KernelVersion:	3.20
Description:	Color matching descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching/default
Date:		Dec 2014
KernelVersion:	3.20
Description:	Default color matching descriptors

		All attributes read only:
		bMatrixCoefficients	- matrix used to compute luma and
					chroma values from the color primaries
		bTransferCharacteristics- optoelectronic transfer
					characteristic of the source picutre,
					also called the gamma function
		bColorPrimaries		- color primaries and the reference
					white

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg
Date:		Dec 2014
KernelVersion:	3.20
Description:	MJPEG format descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name
Date:		Dec 2014
KernelVersion:	3.20
Description:	Specific MJPEG format descriptors

		All attributes read only,
		except bmaControls and bDefaultFrameIndex:
		bmaControls		- this format's data for bmaControls in
					the streaming header
		bmInterfaceFlags	- specifies interlace information,
					read-only
		bAspectRatioY		- the X dimension of the picture aspect
					ratio, read-only
		bAspectRatioX		- the Y dimension of the picture aspect
					ratio, read-only
		bmFlags			- characteristics of this format,
					read-only
		bDefaultFrameIndex	- optimum frame index for this stream

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name/name
Date:		Dec 2014
KernelVersion:	3.20
Description:	Specific MJPEG frame descriptors

		dwFrameInterval		- indicates how frame interval can be
					programmed; a number of values
					separated by newline can be specified
		dwDefaultFrameInterval	- the frame interval the device would
					like to use as default
		dwMaxVideoFrameBufferSize- the maximum number of bytes the
					compressor will produce for a video
					frame or still image
		dwMaxBitRate		- the maximum bit rate at the shortest
					frame interval in bps
		dwMinBitRate		- the minimum bit rate at the longest
					frame interval in bps
		wHeight			- height of decoded bitmap frame in px
		wWidth			- width of decoded bitmam frame in px
		bmCapabilities		- still image support, fixed frame-rate
					support

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed
Date:		Dec 2014
KernelVersion:	3.20
Description:	Uncompressed format descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name
Date:		Dec 2014
KernelVersion:	3.20
Description:	Specific uncompressed format descriptors

		bmaControls		- this format's data for bmaControls in
					the streaming header
		bmInterfaceFlags	- specifies interlace information,
					read-only
		bAspectRatioY		- the X dimension of the picture aspect
					ratio, read-only
		bAspectRatioX		- the Y dimension of the picture aspect
					ratio, read-only
		bDefaultFrameIndex	- optimum frame index for this stream
		bBitsPerPixel		- number of bits per pixel used to
					specify color in the decoded video
					frame
		guidFormat		- globally unique id used to identify
					stream-encoding format

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name/name
Date:		Dec 2014
KernelVersion:	3.20
Description:	Specific uncompressed frame descriptors

		dwFrameInterval		- indicates how frame interval can be
					programmed; a number of values
					separated by newline can be specified
		dwDefaultFrameInterval	- the frame interval the device would
					like to use as default
		dwMaxVideoFrameBufferSize- the maximum number of bytes the
					compressor will produce for a video
					frame or still image
		dwMaxBitRate		- the maximum bit rate at the shortest
					frame interval in bps
		dwMinBitRate		- the minimum bit rate at the longest
					frame interval in bps
		wHeight			- height of decoded bitmap frame in px
		wWidth			- width of decoded bitmam frame in px
		bmCapabilities		- still image support, fixed frame-rate
					support

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/header
Date:		Dec 2014
KernelVersion:	3.20
Description:	Streaming header descriptors

What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/header/name
Date:		Dec 2014
KernelVersion:	3.20
Description:	Specific streaming header descriptors

		All attributes read only:
		bTriggerUsage		- how the host software will respond to
					a hardware trigger interrupt event
		bTriggerSupport		- flag specifying if hardware
					triggering is supported
		bStillCaptureMethod	- method of still image caputre
					supported
		bTerminalLink		- id of the output terminal to which
					the video endpoint of this interface
					is connected
		bmInfo			- capabilities of this video streaming
					interface
+11 −0
Original line number Diff line number Diff line
@@ -423,6 +423,17 @@ config USB_CONFIGFS_F_HID

	  For more information, see Documentation/usb/gadget_hid.txt.

config USB_CONFIGFS_F_UVC
	boolean "USB Webcam function"
	depends on USB_CONFIGFS
	depends on VIDEO_DEV
	select VIDEOBUF2_VMALLOC
	select USB_F_UVC
	help
	  The Webcam function acts as a composite USB Audio and Video Class
	  device. It provides a userspace API to process UVC control requests
	  and stream video data to the host.

source "drivers/usb/gadget/legacy/Kconfig"

endchoice
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ usb_f_uac1-y := f_uac1.o u_uac1.o
obj-$(CONFIG_USB_F_UAC1)	+= usb_f_uac1.o
usb_f_uac2-y			:= f_uac2.o
obj-$(CONFIG_USB_F_UAC2)	+= usb_f_uac2.o
usb_f_uvc-y			:= f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o
usb_f_uvc-y			:= f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
obj-$(CONFIG_USB_F_UVC)		+= usb_f_uvc.o
usb_f_midi-y			:= f_midi.o
obj-$(CONFIG_USB_F_MIDI)	+= usb_f_midi.o
+103 −3
Original line number Diff line number Diff line
@@ -27,10 +27,11 @@
#include <media/v4l2-dev.h>
#include <media/v4l2-event.h>

#include "u_uvc.h"
#include "uvc.h"
#include "uvc_configfs.h"
#include "uvc_v4l2.h"
#include "uvc_video.h"
#include "u_uvc.h"

unsigned int uvc_gadget_trace_param;

@@ -788,25 +789,104 @@ static void uvc_free_inst(struct usb_function_instance *f)
{
	struct f_uvc_opts *opts = fi_to_f_uvc_opts(f);

	mutex_destroy(&opts->lock);
	kfree(opts);
}

static struct usb_function_instance *uvc_alloc_inst(void)
{
	struct f_uvc_opts *opts;
	struct uvc_camera_terminal_descriptor *cd;
	struct uvc_processing_unit_descriptor *pd;
	struct uvc_output_terminal_descriptor *od;
	struct uvc_color_matching_descriptor *md;
	struct uvc_descriptor_header **ctl_cls;

	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
	if (!opts)
		return ERR_PTR(-ENOMEM);
	opts->func_inst.free_func_inst = uvc_free_inst;

	mutex_init(&opts->lock);

	cd = &opts->uvc_camera_terminal;
	cd->bLength			= UVC_DT_CAMERA_TERMINAL_SIZE(3);
	cd->bDescriptorType		= USB_DT_CS_INTERFACE;
	cd->bDescriptorSubType		= UVC_VC_INPUT_TERMINAL;
	cd->bTerminalID			= 1;
	cd->wTerminalType		= cpu_to_le16(0x0201);
	cd->bAssocTerminal		= 0;
	cd->iTerminal			= 0;
	cd->wObjectiveFocalLengthMin	= cpu_to_le16(0);
	cd->wObjectiveFocalLengthMax	= cpu_to_le16(0);
	cd->wOcularFocalLength		= cpu_to_le16(0);
	cd->bControlSize		= 3;
	cd->bmControls[0]		= 2;
	cd->bmControls[1]		= 0;
	cd->bmControls[2]		= 0;

	pd = &opts->uvc_processing;
	pd->bLength			= UVC_DT_PROCESSING_UNIT_SIZE(2);
	pd->bDescriptorType		= USB_DT_CS_INTERFACE;
	pd->bDescriptorSubType		= UVC_VC_PROCESSING_UNIT;
	pd->bUnitID			= 2;
	pd->bSourceID			= 1;
	pd->wMaxMultiplier		= cpu_to_le16(16*1024);
	pd->bControlSize		= 2;
	pd->bmControls[0]		= 1;
	pd->bmControls[1]		= 0;
	pd->iProcessing			= 0;

	od = &opts->uvc_output_terminal;
	od->bLength			= UVC_DT_OUTPUT_TERMINAL_SIZE;
	od->bDescriptorType		= USB_DT_CS_INTERFACE;
	od->bDescriptorSubType		= UVC_VC_OUTPUT_TERMINAL;
	od->bTerminalID			= 3;
	od->wTerminalType		= cpu_to_le16(0x0101);
	od->bAssocTerminal		= 0;
	od->bSourceID			= 2;
	od->iTerminal			= 0;

	md = &opts->uvc_color_matching;
	md->bLength			= UVC_DT_COLOR_MATCHING_SIZE;
	md->bDescriptorType		= USB_DT_CS_INTERFACE;
	md->bDescriptorSubType		= UVC_VS_COLORFORMAT;
	md->bColorPrimaries		= 1;
	md->bTransferCharacteristics	= 1;
	md->bMatrixCoefficients		= 4;

	/* Prepare fs control class descriptors for configfs-based gadgets */
	ctl_cls = opts->uvc_fs_control_cls;
	ctl_cls[0] = NULL;	/* assigned elsewhere by configfs */
	ctl_cls[1] = (struct uvc_descriptor_header *)cd;
	ctl_cls[2] = (struct uvc_descriptor_header *)pd;
	ctl_cls[3] = (struct uvc_descriptor_header *)od;
	ctl_cls[4] = NULL;	/* NULL-terminate */
	opts->fs_control =
		(const struct uvc_descriptor_header * const *)ctl_cls;

	/* Prepare hs control class descriptors for configfs-based gadgets */
	ctl_cls = opts->uvc_ss_control_cls;
	ctl_cls[0] = NULL;	/* assigned elsewhere by configfs */
	ctl_cls[1] = (struct uvc_descriptor_header *)cd;
	ctl_cls[2] = (struct uvc_descriptor_header *)pd;
	ctl_cls[3] = (struct uvc_descriptor_header *)od;
	ctl_cls[4] = NULL;	/* NULL-terminate */
	opts->ss_control =
		(const struct uvc_descriptor_header * const *)ctl_cls;

	opts->streaming_interval = 1;
	opts->streaming_maxpacket = 1024;

	uvcg_attach_configfs(opts);
	return &opts->func_inst;
}

static void uvc_free(struct usb_function *f)
{
	struct uvc_device *uvc = to_uvc(f);

	struct f_uvc_opts *opts = container_of(f->fi, struct f_uvc_opts,
					       func_inst);
	--opts->refcnt;
	kfree(uvc);
}

@@ -832,6 +912,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
{
	struct uvc_device *uvc;
	struct f_uvc_opts *opts;
	struct uvc_descriptor_header **strm_cls;

	uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
	if (uvc == NULL)
@@ -840,11 +921,30 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
	uvc->state = UVC_STATE_DISCONNECTED;
	opts = fi_to_f_uvc_opts(fi);

	mutex_lock(&opts->lock);
	if (opts->uvc_fs_streaming_cls) {
		strm_cls = opts->uvc_fs_streaming_cls;
		opts->fs_streaming =
			(const struct uvc_descriptor_header * const *)strm_cls;
	}
	if (opts->uvc_hs_streaming_cls) {
		strm_cls = opts->uvc_hs_streaming_cls;
		opts->hs_streaming =
			(const struct uvc_descriptor_header * const *)strm_cls;
	}
	if (opts->uvc_ss_streaming_cls) {
		strm_cls = opts->uvc_ss_streaming_cls;
		opts->ss_streaming =
			(const struct uvc_descriptor_header * const *)strm_cls;
	}

	uvc->desc.fs_control = opts->fs_control;
	uvc->desc.ss_control = opts->ss_control;
	uvc->desc.fs_streaming = opts->fs_streaming;
	uvc->desc.hs_streaming = opts->hs_streaming;
	uvc->desc.ss_streaming = opts->ss_streaming;
	++opts->refcnt;
	mutex_unlock(&opts->lock);

	/* Register the function. */
	uvc->func.name = "uvc";
+50 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define U_UVC_H

#include <linux/usb/composite.h>
#include <linux/usb/video.h>

#define fi_to_f_uvc_opts(f)	container_of(f, struct f_uvc_opts, func_inst)

@@ -26,11 +27,60 @@ struct f_uvc_opts {
	unsigned int					streaming_interval;
	unsigned int					streaming_maxpacket;
	unsigned int					streaming_maxburst;

	/*
	 * Control descriptors array pointers for full-/high-speed and
	 * super-speed. They point by default to the uvc_fs_control_cls and
	 * uvc_ss_control_cls arrays respectively. Legacy gadgets must
	 * override them in their gadget bind callback.
	 */
	const struct uvc_descriptor_header * const	*fs_control;
	const struct uvc_descriptor_header * const	*ss_control;

	/*
	 * Streaming descriptors array pointers for full-speed, high-speed and
	 * super-speed. They will point to the uvc_[fhs]s_streaming_cls arrays
	 * for configfs-based gadgets. Legacy gadgets must initialize them in
	 * their gadget bind callback.
	 */
	const struct uvc_descriptor_header * const	*fs_streaming;
	const struct uvc_descriptor_header * const	*hs_streaming;
	const struct uvc_descriptor_header * const	*ss_streaming;

	/* Default control descriptors for configfs-based gadgets. */
	struct uvc_camera_terminal_descriptor		uvc_camera_terminal;
	struct uvc_processing_unit_descriptor		uvc_processing;
	struct uvc_output_terminal_descriptor		uvc_output_terminal;
	struct uvc_color_matching_descriptor		uvc_color_matching;

	/*
	 * Control descriptors pointers arrays for full-/high-speed and
	 * super-speed. The first element is a configurable control header
	 * descriptor, the other elements point to the fixed default control
	 * descriptors. Used by configfs only, must not be touched by legacy
	 * gadgets.
	 */
	struct uvc_descriptor_header			*uvc_fs_control_cls[5];
	struct uvc_descriptor_header			*uvc_ss_control_cls[5];

	/*
	 * Streaming descriptors for full-speed, high-speed and super-speed.
	 * Used by configfs only, must not be touched by legacy gadgets. The
	 * arrays are allocated at runtime as the number of descriptors isn't
	 * known in advance.
	 */
	struct uvc_descriptor_header			**uvc_fs_streaming_cls;
	struct uvc_descriptor_header			**uvc_hs_streaming_cls;
	struct uvc_descriptor_header			**uvc_ss_streaming_cls;

	/*
	 * Read/write access to configfs attributes is handled by configfs.
	 *
	 * This lock protects the descriptors from concurrent access by
	 * read/write and symlink creation/removal.
	 */
	struct mutex			lock;
	int				refcnt;
};

void uvc_set_trace_param(unsigned int trace);
Loading