/* SPDX-License-Identifier: GPL-2.0+ *//* * uvc_gadget.h -- USB Video Class Gadget driver * * Copyright (C) 2009-2010 * Laurent Pinchart (laurent.pinchart@ideasonboard.com) */ #ifndef _UVC_GADGET_H_#define _UVC_GADGET_H_ #include <linux/list.h>#include <linux/mutex.h>#include <linux/spinlock.h>#include <linux/usb/composite.h>#include <linux/videodev2.h>#include <linux/wait.h> #include <media/v4l2-device.h>#include <media/v4l2-dev.h>#include <media/v4l2-fh.h> #include "uvc_queue.h" struct usb_ep;struct usb_request;struct uvc_descriptor_header;struct uvc_device; /* ------------------------------------------------------------------------ * Debugging, printing and logging */ #define UVC_TRACE_PROBE (1 << 0)#define UVC_TRACE_DESCR (1 << 1)#define UVC_TRACE_CONTROL (1 << 2)#define UVC_TRACE_FORMAT (1 << 3)#define UVC_TRACE_CAPTURE (1 << 4)#define UVC_TRACE_CALLS (1 << 5)#define UVC_TRACE_IOCTL (1 << 6)#define UVC_TRACE_FRAME (1 << 7)#define UVC_TRACE_SUSPEND (1 << 8)#define UVC_TRACE_STATUS (1 << 9) #define UVC_WARN_MINMAX 0#define UVC_WARN_PROBE_DEF 1 extern unsigned int uvc_gadget_trace_param; #define uvc_trace(flag, msg...) \ do { \ if (uvc_gadget_trace_param & flag) \ printk(KERN_DEBUG "uvcvideo: " msg); \ } while (0) #define uvcg_dbg(f, fmt, args...) \ dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)#define uvcg_info(f, fmt, args...) \ dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)#define uvcg_warn(f, fmt, args...) \ dev_warn(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)#define uvcg_err(f, fmt, args...) \ dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args) /* ------------------------------------------------------------------------ * Driver specific constants */ #define UVC_MAX_REQUEST_SIZE 64#define UVC_MAX_EVENTS 4 #define UVCG_REQUEST_HEADER_LEN 12 #define UVCG_REQ_MAX_INT_COUNT 16#define UVCG_REQ_MAX_ZERO_COUNT (2 * UVCG_REQ_MAX_INT_COUNT) #define UVCG_STREAMING_MIN_BUFFERS 2 /* ------------------------------------------------------------------------ * Structures */struct uvc_request { struct usb_request *req; u8 *req_buffer; struct uvc_video *video; struct sg_table sgt; u8 header[UVCG_REQUEST_HEADER_LEN]; struct uvc_buffer *last_buf; struct list_head list;}; struct uvc_video { struct uvc_device *uvc; struct usb_ep *ep; struct work_struct pump; struct workqueue_struct *async_wq; struct kthread_worker *kworker; struct kthread_work hw_submit; atomic_t queued; /* Frame parameters */ u8 bpp; u32 fcc; unsigned int width; unsigned int height; unsigned int imagesize; unsigned int interval; /* in 100ns units */ struct mutex mutex; /* protects frame parameters */ unsigned int uvc_num_requests; unsigned int reqs_per_frame; /* Requests */ bool is_enabled; /* tracks whether video stream is enabled */ unsigned int req_size; unsigned int max_req_size; struct list_head ureqs; /* all uvc_requests allocated by uvc_video */ /* USB requests that the video pump thread can encode into */ struct list_head req_free; /* * USB requests video pump thread has already encoded into. These are * ready to be queued to the endpoint. */ struct list_head req_ready; spinlock_t req_lock; unsigned int req_int_count; void (*encode) (struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf); /* Context data used by the completion handler */ __u32 payload_size; __u32 max_payload_size; struct uvc_video_queue queue; unsigned int fid;}; enum uvc_state { UVC_STATE_DISCONNECTED, UVC_STATE_CONNECTED, UVC_STATE_STREAMING,}; struct uvc_device { struct video_device vdev; struct v4l2_device v4l2_dev; enum uvc_state state; struct usb_function func; struct uvc_video video; struct completion *vdev_release_done; struct mutex lock; /* protects func_unbound and func_connected */ bool func_unbound; bool func_connected; wait_queue_head_t func_connected_queue; struct uvcg_streaming_header *header; /* Descriptors */ struct { const struct uvc_descriptor_header * const *fs_control; const struct uvc_descriptor_header * const *ss_control; const struct uvc_descriptor_header * const *fs_streaming; const struct uvc_descriptor_header * const *hs_streaming; const struct uvc_descriptor_header * const *ss_streaming; struct list_head *extension_units; } desc; unsigned int control_intf; struct usb_ep *interrupt_ep; struct usb_request *control_req; void *control_buf; bool enable_interrupt_ep; unsigned int streaming_intf; /* Events */ unsigned int event_length; unsigned int event_setup_out : 1;}; static inline struct uvc_device *to_uvc(struct usb_function *f){ return container_of(f, struct uvc_device, func);} struct uvc_file_handle { struct v4l2_fh vfh; struct uvc_video *device; bool is_uvc_app_handle;}; #define to_uvc_file_handle(handle) \ container_of(handle, struct uvc_file_handle, vfh) static inline struct uvc_file_handle *file_to_uvc_file_handle(struct file *filp){ return container_of(file_to_v4l2_fh(filp), struct uvc_file_handle, vfh);} /* ------------------------------------------------------------------------ * Functions */ extern void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep);extern void uvc_function_connect(struct uvc_device *uvc);extern void uvc_function_disconnect(struct uvc_device *uvc); #endif /* _UVC_GADGET_H_ */
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* uvc_gadget.h -- USB Video Class Gadget driver
*
* Copyright (C) 2009-2010
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*/
#ifndef _UVC_GADGET_H_
#define _UVC_GADGET_H_
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/usb/composite.h>
#include <linux/videodev2.h>
#include <linux/wait.h>
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-fh.h>
#include "uvc_queue.h"
struct usb_ep;
struct usb_request;
struct uvc_descriptor_header;
struct uvc_device;
/* ------------------------------------------------------------------------
* Debugging, printing and logging
*/
#define UVC_TRACE_PROBE (1 << 0)
#define UVC_TRACE_DESCR (1 << 1)
#define UVC_TRACE_CONTROL (1 << 2)
#define UVC_TRACE_FORMAT (1 << 3)
#define UVC_TRACE_CAPTURE (1 << 4)
#define UVC_TRACE_CALLS (1 << 5)
#define UVC_TRACE_IOCTL (1 << 6)
#define UVC_TRACE_FRAME (1 << 7)
#define UVC_TRACE_SUSPEND (1 << 8)
#define UVC_TRACE_STATUS (1 << 9)
#define UVC_WARN_MINMAX 0
#define UVC_WARN_PROBE_DEF 1
extern unsigned int uvc_gadget_trace_param;
#define uvc_trace(flag, msg...) \
do { \
if (uvc_gadget_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
#define uvcg_dbg(f, fmt, args...) \
dev_dbg(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_info(f, fmt, args...) \
dev_info(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_warn(f, fmt, args...) \
dev_warn(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
#define uvcg_err(f, fmt, args...) \
dev_err(&(f)->config->cdev->gadget->dev, "%s: " fmt, (f)->name, ##args)
/* ------------------------------------------------------------------------
* Driver specific constants
*/
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
#define UVCG_REQUEST_HEADER_LEN 12
#define UVCG_REQ_MAX_INT_COUNT 16
#define UVCG_REQ_MAX_ZERO_COUNT (2 * UVCG_REQ_MAX_INT_COUNT)
#define UVCG_STREAMING_MIN_BUFFERS 2
/* ------------------------------------------------------------------------
* Structures
*/
struct uvc_request {
struct usb_request *req;
u8 *req_buffer;
struct uvc_video *video;
struct sg_table sgt;
u8 header[UVCG_REQUEST_HEADER_LEN];
struct uvc_buffer *last_buf;
struct list_head list;
};
struct uvc_video {
struct uvc_device *uvc;
struct usb_ep *ep;
struct work_struct pump;
struct workqueue_struct *async_wq;
struct kthread_worker *kworker;
struct kthread_work hw_submit;
atomic_t queued;
/* Frame parameters */
u8 bpp;
u32 fcc;
unsigned int width;
unsigned int height;
unsigned int imagesize;
unsigned int interval; /* in 100ns units */
struct mutex mutex; /* protects frame parameters */
unsigned int uvc_num_requests;
unsigned int reqs_per_frame;
/* Requests */
bool is_enabled; /* tracks whether video stream is enabled */
unsigned int req_size;
unsigned int max_req_size;
struct list_head ureqs; /* all uvc_requests allocated by uvc_video */
/* USB requests that the video pump thread can encode into */
struct list_head req_free;
/*
* USB requests video pump thread has already encoded into. These are
* ready to be queued to the endpoint.
*/
struct list_head req_ready;
spinlock_t req_lock;
unsigned int req_int_count;
void (*encode) (struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf);
/* Context data used by the completion handler */
__u32 payload_size;
__u32 max_payload_size;
struct uvc_video_queue queue;
unsigned int fid;
};
enum uvc_state {
UVC_STATE_DISCONNECTED,
UVC_STATE_CONNECTED,
UVC_STATE_STREAMING,
};
struct uvc_device {
struct video_device vdev;
struct v4l2_device v4l2_dev;
enum uvc_state state;
struct usb_function func;
struct uvc_video video;
struct completion *vdev_release_done;
struct mutex lock; /* protects func_unbound and func_connected */
bool func_unbound;
bool func_connected;
wait_queue_head_t func_connected_queue;
struct uvcg_streaming_header *header;
/* Descriptors */
struct {
const struct uvc_descriptor_header * const *fs_control;
const struct uvc_descriptor_header * const *ss_control;
const struct uvc_descriptor_header * const *fs_streaming;
const struct uvc_descriptor_header * const *hs_streaming;
const struct uvc_descriptor_header * const *ss_streaming;
struct list_head *extension_units;
} desc;
unsigned int control_intf;
struct usb_ep *interrupt_ep;
struct usb_request *control_req;
void *control_buf;
bool enable_interrupt_ep;
unsigned int streaming_intf;
/* Events */
unsigned int event_length;
unsigned int event_setup_out : 1;
};
static inline struct uvc_device *to_uvc(struct usb_function *f)
{
return container_of(f, struct uvc_device, func);
}
struct uvc_file_handle {
struct v4l2_fh vfh;
struct uvc_video *device;
bool is_uvc_app_handle;
};
#define to_uvc_file_handle(handle) \
container_of(handle, struct uvc_file_handle, vfh)
static inline struct uvc_file_handle *file_to_uvc_file_handle(struct file *filp)
{
return container_of(file_to_v4l2_fh(filp), struct uvc_file_handle, vfh);
}
/* ------------------------------------------------------------------------
* Functions
*/
extern void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep);
extern void uvc_function_connect(struct uvc_device *uvc);
extern void uvc_function_disconnect(struct uvc_device *uvc);
#endif /* _UVC_GADGET_H_ */