usb: gadget: uvc: separately compile some components of f_uvc
Compile uvc_queue, uvc_v4l2, uvc_video separately so that later they can be all combined in a separately compiled f_uvc. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Tested-by: Michael Grzeschik <m.grzeschik@pengutronix.de> [Make uvc_v4l2_ioctl_ops non-static] [Rename __UVC__V4L2__H__ and __UVC__VIDEO__H__] [Update MAINTAINERS] Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
7ea95b1108
commit
3a83c16ef0
12 changed files with 118 additions and 37 deletions
|
@ -9669,7 +9669,7 @@ USB WEBCAM GADGET
|
||||||
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||||
L: linux-usb@vger.kernel.org
|
L: linux-usb@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/usb/gadget/function/*uvc*.c
|
F: drivers/usb/gadget/function/*uvc*
|
||||||
F: drivers/usb/gadget/legacy/webcam.c
|
F: drivers/usb/gadget/legacy/webcam.c
|
||||||
|
|
||||||
USB WIRELESS RNDIS DRIVER (rndis_wlan)
|
USB WIRELESS RNDIS DRIVER (rndis_wlan)
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include <media/v4l2-event.h>
|
#include <media/v4l2-event.h>
|
||||||
|
|
||||||
#include "uvc.h"
|
#include "uvc.h"
|
||||||
|
#include "uvc_v4l2.h"
|
||||||
|
#include "uvc_video.h"
|
||||||
|
|
||||||
unsigned int uvc_gadget_trace_param;
|
unsigned int uvc_gadget_trace_param;
|
||||||
static unsigned int streaming_interval;
|
static unsigned int streaming_interval;
|
||||||
|
|
|
@ -16,6 +16,14 @@
|
||||||
#include <linux/usb/composite.h>
|
#include <linux/usb/composite.h>
|
||||||
#include <linux/usb/video.h>
|
#include <linux/usb/video.h>
|
||||||
|
|
||||||
|
#include "uvc.h"
|
||||||
|
|
||||||
|
void uvc_function_setup_continue(struct uvc_device *uvc);
|
||||||
|
|
||||||
|
void uvc_function_connect(struct uvc_device *uvc);
|
||||||
|
|
||||||
|
void uvc_function_disconnect(struct uvc_device *uvc);
|
||||||
|
|
||||||
int uvc_bind_config(struct usb_configuration *c,
|
int uvc_bind_config(struct usb_configuration *c,
|
||||||
const struct uvc_descriptor_header * const *fs_control,
|
const struct uvc_descriptor_header * const *fs_control,
|
||||||
const struct uvc_descriptor_header * const *hs_control,
|
const struct uvc_descriptor_header * const *hs_control,
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct uvc_event
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#include <linux/usb.h> /* For usb_endpoint_* */
|
#include <linux/usb.h> /* For usb_endpoint_* */
|
||||||
|
#include <linux/usb/composite.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
|
@ -126,8 +126,7 @@ static struct vb2_ops uvc_queue_qops = {
|
||||||
.wait_finish = uvc_wait_finish,
|
.wait_finish = uvc_wait_finish,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int uvcg_queue_init(struct uvc_video_queue *queue,
|
int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
|
||||||
enum v4l2_buf_type type)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -154,7 +153,7 @@ static int uvcg_queue_init(struct uvc_video_queue *queue,
|
||||||
/*
|
/*
|
||||||
* Free the video buffers.
|
* Free the video buffers.
|
||||||
*/
|
*/
|
||||||
static void uvcg_free_buffers(struct uvc_video_queue *queue)
|
void uvcg_free_buffers(struct uvc_video_queue *queue)
|
||||||
{
|
{
|
||||||
mutex_lock(&queue->mutex);
|
mutex_lock(&queue->mutex);
|
||||||
vb2_queue_release(&queue->queue);
|
vb2_queue_release(&queue->queue);
|
||||||
|
@ -164,7 +163,7 @@ static void uvcg_free_buffers(struct uvc_video_queue *queue)
|
||||||
/*
|
/*
|
||||||
* Allocate the video buffers.
|
* Allocate the video buffers.
|
||||||
*/
|
*/
|
||||||
static int uvcg_alloc_buffers(struct uvc_video_queue *queue,
|
int uvcg_alloc_buffers(struct uvc_video_queue *queue,
|
||||||
struct v4l2_requestbuffers *rb)
|
struct v4l2_requestbuffers *rb)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -176,8 +175,7 @@ static int uvcg_alloc_buffers(struct uvc_video_queue *queue,
|
||||||
return ret ? ret : rb->count;
|
return ret ? ret : rb->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uvcg_query_buffer(struct uvc_video_queue *queue,
|
int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
|
||||||
struct v4l2_buffer *buf)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -188,8 +186,7 @@ static int uvcg_query_buffer(struct uvc_video_queue *queue,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uvcg_queue_buffer(struct uvc_video_queue *queue,
|
int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
|
||||||
struct v4l2_buffer *buf)
|
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -213,8 +210,8 @@ done:
|
||||||
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
|
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
|
||||||
* available.
|
* available.
|
||||||
*/
|
*/
|
||||||
static int uvcg_dequeue_buffer(struct uvc_video_queue *queue,
|
int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
|
||||||
struct v4l2_buffer *buf, int nonblocking)
|
int nonblocking)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -231,8 +228,8 @@ static int uvcg_dequeue_buffer(struct uvc_video_queue *queue,
|
||||||
* This function implements video queue polling and is intended to be used by
|
* This function implements video queue polling and is intended to be used by
|
||||||
* the device poll handler.
|
* the device poll handler.
|
||||||
*/
|
*/
|
||||||
static unsigned int uvcg_queue_poll(struct uvc_video_queue *queue,
|
unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file,
|
||||||
struct file *file, poll_table *wait)
|
poll_table *wait)
|
||||||
{
|
{
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
|
|
||||||
|
@ -243,8 +240,7 @@ static unsigned int uvcg_queue_poll(struct uvc_video_queue *queue,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uvcg_queue_mmap(struct uvc_video_queue *queue,
|
int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
|
||||||
struct vm_area_struct *vma)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -261,9 +257,8 @@ static int uvcg_queue_mmap(struct uvc_video_queue *queue,
|
||||||
*
|
*
|
||||||
* NO-MMU arch need this function to make mmap() work correctly.
|
* NO-MMU arch need this function to make mmap() work correctly.
|
||||||
*/
|
*/
|
||||||
static unsigned long uvcg_queue_get_unmapped_area(
|
unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue,
|
||||||
struct uvc_video_queue *queue,
|
unsigned long pgoff)
|
||||||
unsigned long pgoff)
|
|
||||||
{
|
{
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
|
|
||||||
|
@ -286,7 +281,7 @@ static unsigned long uvcg_queue_get_unmapped_area(
|
||||||
* This function acquires the irq spinlock and can be called from interrupt
|
* This function acquires the irq spinlock and can be called from interrupt
|
||||||
* context.
|
* context.
|
||||||
*/
|
*/
|
||||||
static void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
|
void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
|
||||||
{
|
{
|
||||||
struct uvc_buffer *buf;
|
struct uvc_buffer *buf;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -327,7 +322,7 @@ static void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
|
||||||
* This function can't be called from interrupt context. Use
|
* This function can't be called from interrupt context. Use
|
||||||
* uvcg_queue_cancel() instead.
|
* uvcg_queue_cancel() instead.
|
||||||
*/
|
*/
|
||||||
static int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
|
int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -364,8 +359,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called with &queue_irqlock held.. */
|
/* called with &queue_irqlock held.. */
|
||||||
static struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
|
struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
|
||||||
struct uvc_buffer *buf)
|
struct uvc_buffer *buf)
|
||||||
{
|
{
|
||||||
struct uvc_buffer *nextbuf;
|
struct uvc_buffer *nextbuf;
|
||||||
|
|
||||||
|
@ -393,7 +388,7 @@ static struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
|
||||||
return nextbuf;
|
return nextbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue)
|
struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue)
|
||||||
{
|
{
|
||||||
struct uvc_buffer *buf = NULL;
|
struct uvc_buffer *buf = NULL;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,39 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
|
||||||
return vb2_is_streaming(&queue->queue);
|
return vb2_is_streaming(&queue->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type);
|
||||||
|
|
||||||
|
void uvcg_free_buffers(struct uvc_video_queue *queue);
|
||||||
|
|
||||||
|
int uvcg_alloc_buffers(struct uvc_video_queue *queue,
|
||||||
|
struct v4l2_requestbuffers *rb);
|
||||||
|
|
||||||
|
int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf);
|
||||||
|
|
||||||
|
int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf);
|
||||||
|
|
||||||
|
int uvcg_dequeue_buffer(struct uvc_video_queue *queue,
|
||||||
|
struct v4l2_buffer *buf, int nonblocking);
|
||||||
|
|
||||||
|
unsigned int uvcg_queue_poll(struct uvc_video_queue *queue,
|
||||||
|
struct file *file, poll_table *wait);
|
||||||
|
|
||||||
|
int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma);
|
||||||
|
|
||||||
|
#ifndef CONFIG_MMU
|
||||||
|
unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue,
|
||||||
|
unsigned long pgoff);
|
||||||
|
#endif /* CONFIG_MMU */
|
||||||
|
|
||||||
|
void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect);
|
||||||
|
|
||||||
|
int uvcg_queue_enable(struct uvc_video_queue *queue, int enable);
|
||||||
|
|
||||||
|
struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
|
||||||
|
struct uvc_buffer *buf);
|
||||||
|
|
||||||
|
struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* _UVC_QUEUE_H_ */
|
#endif /* _UVC_QUEUE_H_ */
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
#include <media/v4l2-event.h>
|
#include <media/v4l2-event.h>
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
|
|
||||||
|
#include "f_uvc.h"
|
||||||
#include "uvc.h"
|
#include "uvc.h"
|
||||||
#include "uvc_queue.h"
|
#include "uvc_queue.h"
|
||||||
|
#include "uvc_video.h"
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* Requests handling
|
* Requests handling
|
||||||
|
@ -259,7 +261,7 @@ uvc_v4l2_ioctl_default(struct file *file, void *fh, bool valid_prio,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = {
|
const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = {
|
||||||
.vidioc_querycap = uvc_v4l2_querycap,
|
.vidioc_querycap = uvc_v4l2_querycap,
|
||||||
.vidioc_g_fmt_vid_out = uvc_v4l2_get_format,
|
.vidioc_g_fmt_vid_out = uvc_v4l2_get_format,
|
||||||
.vidioc_s_fmt_vid_out = uvc_v4l2_set_format,
|
.vidioc_s_fmt_vid_out = uvc_v4l2_set_format,
|
||||||
|
@ -350,7 +352,7 @@ static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct v4l2_file_operations uvc_v4l2_fops = {
|
struct v4l2_file_operations uvc_v4l2_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = uvc_v4l2_open,
|
.open = uvc_v4l2_open,
|
||||||
.release = uvc_v4l2_release,
|
.release = uvc_v4l2_release,
|
||||||
|
|
22
drivers/usb/gadget/function/uvc_v4l2.h
Normal file
22
drivers/usb/gadget/function/uvc_v4l2.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* uvc_v4l2.h -- USB Video Class Gadget driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2010
|
||||||
|
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||||
|
* http://www.samsung.com
|
||||||
|
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UVC_V4L2_H__
|
||||||
|
#define __UVC_V4L2_H__
|
||||||
|
|
||||||
|
extern const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops;
|
||||||
|
extern struct v4l2_file_operations uvc_v4l2_fops;
|
||||||
|
|
||||||
|
#endif /* __UVC_V4L2_H__ */
|
|
@ -15,6 +15,7 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
|
#include <linux/usb/video.h>
|
||||||
|
|
||||||
#include <media/v4l2-dev.h>
|
#include <media/v4l2-dev.h>
|
||||||
|
|
||||||
|
@ -279,8 +280,7 @@ error:
|
||||||
* This function fills the available USB requests (listed in req_free) with
|
* This function fills the available USB requests (listed in req_free) with
|
||||||
* video data from the queued buffers.
|
* video data from the queued buffers.
|
||||||
*/
|
*/
|
||||||
static int
|
int uvcg_video_pump(struct uvc_video *video)
|
||||||
uvcg_video_pump(struct uvc_video *video)
|
|
||||||
{
|
{
|
||||||
struct uvc_video_queue *queue = &video->queue;
|
struct uvc_video_queue *queue = &video->queue;
|
||||||
struct usb_request *req;
|
struct usb_request *req;
|
||||||
|
@ -339,8 +339,7 @@ uvcg_video_pump(struct uvc_video *video)
|
||||||
/*
|
/*
|
||||||
* Enable or disable the video stream.
|
* Enable or disable the video stream.
|
||||||
*/
|
*/
|
||||||
static int
|
int uvcg_video_enable(struct uvc_video *video, int enable)
|
||||||
uvcg_video_enable(struct uvc_video *video, int enable)
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -378,8 +377,7 @@ uvcg_video_enable(struct uvc_video *video, int enable)
|
||||||
/*
|
/*
|
||||||
* Initialize the UVC video stream.
|
* Initialize the UVC video stream.
|
||||||
*/
|
*/
|
||||||
static int
|
int uvcg_video_init(struct uvc_video *video)
|
||||||
uvcg_video_init(struct uvc_video *video)
|
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&video->req_free);
|
INIT_LIST_HEAD(&video->req_free);
|
||||||
spin_lock_init(&video->req_lock);
|
spin_lock_init(&video->req_lock);
|
||||||
|
|
24
drivers/usb/gadget/function/uvc_video.h
Normal file
24
drivers/usb/gadget/function/uvc_video.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* uvc_video.h -- USB Video Class Gadget driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2010
|
||||||
|
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||||
|
* http://www.samsung.com
|
||||||
|
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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.
|
||||||
|
*/
|
||||||
|
#ifndef __UVC_VIDEO_H__
|
||||||
|
#define __UVC_VIDEO_H__
|
||||||
|
|
||||||
|
int uvcg_video_pump(struct uvc_video *video);
|
||||||
|
|
||||||
|
int uvcg_video_enable(struct uvc_video *video, int enable);
|
||||||
|
|
||||||
|
int uvcg_video_init(struct uvc_video *video);
|
||||||
|
|
||||||
|
#endif /* __UVC_VIDEO_H__ */
|
|
@ -19,7 +19,7 @@ g_multi-y := multi.o
|
||||||
g_hid-y := hid.o
|
g_hid-y := hid.o
|
||||||
g_dbgp-y := dbgp.o
|
g_dbgp-y := dbgp.o
|
||||||
g_nokia-y := nokia.o
|
g_nokia-y := nokia.o
|
||||||
g_webcam-y := webcam.o
|
g_webcam-y := webcam.o ../function/uvc_queue.o ../function/uvc_v4l2.o ../function/uvc_video.o
|
||||||
g_ncm-y := ncm.o
|
g_ncm-y := ncm.o
|
||||||
g_acm_ms-y := acm_ms.o
|
g_acm_ms-y := acm_ms.o
|
||||||
g_tcm_usb_gadget-y := tcm_usb_gadget.o
|
g_tcm_usb_gadget-y := tcm_usb_gadget.o
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/module.h>
|
||||||
#include <linux/usb/video.h>
|
#include <linux/usb/video.h>
|
||||||
|
|
||||||
#include "f_uvc.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kbuild is not very cooperative with respect to linking separately
|
* Kbuild is not very cooperative with respect to linking separately
|
||||||
* compiled library objects into one module. So for now we won't use
|
* compiled library objects into one module. So for now we won't use
|
||||||
|
@ -23,9 +22,6 @@
|
||||||
* the runtime footprint, and giving us at least some parts of what
|
* the runtime footprint, and giving us at least some parts of what
|
||||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||||
*/
|
*/
|
||||||
#include "uvc_queue.c"
|
|
||||||
#include "uvc_video.c"
|
|
||||||
#include "uvc_v4l2.c"
|
|
||||||
#include "f_uvc.c"
|
#include "f_uvc.c"
|
||||||
|
|
||||||
USB_GADGET_COMPOSITE_OPTIONS();
|
USB_GADGET_COMPOSITE_OPTIONS();
|
||||||
|
|
Loading…
Reference in a new issue