Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/usb/gadget/legacy/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 19 kB image not shown  

Quelle  webcam.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * webcam.c -- USB webcam gadget driver
 *
 * Copyright (C) 2009-2010
 *     Laurent Pinchart (laurent.pinchart@ideasonboard.com)
 */


#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/usb/video.h>

#include "u_uvc.h"
#include "uvc_configfs.h"

USB_GADGET_COMPOSITE_OPTIONS();

/*-------------------------------------------------------------------------*/

/* module parameters specific to the Video streaming endpoint */
static unsigned int streaming_interval = 1;
module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_interval, "1 - 16");

static unsigned int streaming_maxpacket = 1024;
module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");

static unsigned int streaming_maxburst;
module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");

/* --------------------------------------------------------------------------
 * Device descriptor
 */


#define WEBCAM_VENDOR_ID  0x1d6b /* Linux Foundation */
#define WEBCAM_PRODUCT_ID  0x0102 /* Webcam A/V gadget */
#define WEBCAM_DEVICE_BCD  0x0010 /* 0.10 */

static char webcam_vendor_label[] = "Linux Foundation";
static char webcam_product_label[] = "Webcam gadget";
static char webcam_config_label[] = "Video";

/* string IDs are assigned dynamically */

#define STRING_DESCRIPTION_IDX  USB_GADGET_FIRST_AVAIL_IDX

static struct usb_string webcam_strings[] = {
 [USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label,
 [USB_GADGET_PRODUCT_IDX].s = webcam_product_label,
 [USB_GADGET_SERIAL_IDX].s = "",
 [STRING_DESCRIPTION_IDX].s = webcam_config_label,
 {  }
};

static struct usb_gadget_strings webcam_stringtab = {
 .language = 0x0409, /* en-us */
 .strings = webcam_strings,
};

static struct usb_gadget_strings *webcam_device_strings[] = {
 &webcam_stringtab,
 NULL,
};

static struct usb_function_instance *fi_uvc;
static struct usb_function *f_uvc;

static struct usb_device_descriptor webcam_device_descriptor = {
 .bLength  = USB_DT_DEVICE_SIZE,
 .bDescriptorType = USB_DT_DEVICE,
 /* .bcdUSB = DYNAMIC */
 .bDeviceClass  = USB_CLASS_MISC,
 .bDeviceSubClass = 0x02,
 .bDeviceProtocol = 0x01,
 .bMaxPacketSize0 = 0, /* dynamic */
 .idVendor  = cpu_to_le16(WEBCAM_VENDOR_ID),
 .idProduct  = cpu_to_le16(WEBCAM_PRODUCT_ID),
 .bcdDevice  = cpu_to_le16(WEBCAM_DEVICE_BCD),
 .iManufacturer  = 0, /* dynamic */
 .iProduct  = 0, /* dynamic */
 .iSerialNumber  = 0, /* dynamic */
 .bNumConfigurations = 0, /* dynamic */
};

static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
 .bLength  = UVC_DT_HEADER_SIZE(1),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VC_HEADER,
 .bcdUVC   = cpu_to_le16(0x0110),
 .wTotalLength  = 0, /* dynamic */
 .dwClockFrequency = cpu_to_le32(48000000),
 .bInCollection  = 0, /* dynamic */
 .baInterfaceNr[0] = 0, /* dynamic */
};

static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
 .bLength  = UVC_DT_CAMERA_TERMINAL_SIZE(3),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VC_INPUT_TERMINAL,
 .bTerminalID  = 1,
 .wTerminalType  = cpu_to_le16(0x0201),
 .bAssocTerminal  = 0,
 .iTerminal  = 0,
 .wObjectiveFocalLengthMin = cpu_to_le16(0),
 .wObjectiveFocalLengthMax = cpu_to_le16(0),
 .wOcularFocalLength  = cpu_to_le16(0),
 .bControlSize  = 3,
 .bmControls[0]  = 2,
 .bmControls[1]  = 0,
 .bmControls[2]  = 0,
};

static const struct uvc_processing_unit_descriptor uvc_processing = {
 .bLength  = UVC_DT_PROCESSING_UNIT_SIZE(2),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VC_PROCESSING_UNIT,
 .bUnitID  = 2,
 .bSourceID  = 1,
 .wMaxMultiplier  = cpu_to_le16(16*1024),
 .bControlSize  = 2,
 .bmControls[0]  = 1,
 .bmControls[1]  = 0,
 .iProcessing  = 0,
 .bmVideoStandards = 0,
};

static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
 .bLength  = UVC_DT_OUTPUT_TERMINAL_SIZE,
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL,
 .bTerminalID  = 3,
 .wTerminalType  = cpu_to_le16(0x0101),
 .bAssocTerminal  = 0,
 .bSourceID  = 2,
 .iTerminal  = 0,
};

DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);

static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
 .bLength  = UVC_DT_INPUT_HEADER_SIZE(1, 2),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VS_INPUT_HEADER,
 .bNumFormats  = 2,
 .wTotalLength  = 0, /* dynamic */
 .bEndpointAddress = 0, /* dynamic */
 .bmInfo   = 0,
 .bTerminalLink  = 3,
 .bStillCaptureMethod = 0,
 .bTriggerSupport = 0,
 .bTriggerUsage  = 0,
 .bControlSize  = 1,
 .bmaControls[0][0] = 0,
 .bmaControls[1][0] = 4,
};

static const struct uvcg_color_matching uvcg_color_matching = {
 .desc = {
  .bLength  = UVC_DT_COLOR_MATCHING_SIZE,
  .bDescriptorType = USB_DT_CS_INTERFACE,
  .bDescriptorSubType = UVC_VS_COLORFORMAT,
  .bColorPrimaries = 1,
  .bTransferCharacteristics = 1,
  .bMatrixCoefficients = 4,
 },
};

static struct uvcg_uncompressed uvcg_format_yuv = {
 .fmt = {
  .type   = UVCG_UNCOMPRESSED,
  /* add to .frames and fill .num_frames at runtime */
  .color_matching  = (struct uvcg_color_matching *)&uvcg_color_matching,
 },
 .desc = {
  .bLength  = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
  .bDescriptorType = USB_DT_CS_INTERFACE,
  .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
  .bFormatIndex  = 1,
  .bNumFrameDescriptors = 2,
  .guidFormat  = {
   'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
    0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
  },
  .bBitsPerPixel  = 16,
  .bDefaultFrameIndex = 1,
  .bAspectRatioX  = 0,
  .bAspectRatioY  = 0,
  .bmInterlaceFlags = 0,
  .bCopyProtect  = 0,
 },
};

static struct uvcg_format_ptr uvcg_format_ptr_yuv = {
 .fmt = &uvcg_format_yuv.fmt,
};

DECLARE_UVC_FRAME_UNCOMPRESSED(1);
DECLARE_UVC_FRAME_UNCOMPRESSED(3);

#define UVCG_WIDTH_360P   640
#define UVCG_HEIGHT_360P  360
#define UVCG_MIN_BITRATE_360P  18432000
#define UVCG_MAX_BITRATE_360P  55296000
#define UVCG_MAX_VIDEO_FB_SZ_360P 460800
#define UVCG_FRM_INTERV_0_360P  666666
#define UVCG_FRM_INTERV_1_360P  1000000
#define UVCG_FRM_INTERV_2_360P  5000000
#define UVCG_DEFAULT_FRM_INTERV_360P UVCG_FRM_INTERV_0_360P

static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
 .bLength  = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
 .bFrameIndex  = 1,
 .bmCapabilities  = 0,
 .wWidth   = cpu_to_le16(UVCG_WIDTH_360P),
 .wHeight  = cpu_to_le16(UVCG_HEIGHT_360P),
 .dwMinBitRate  = cpu_to_le32(UVCG_MIN_BITRATE_360P),
 .dwMaxBitRate  = cpu_to_le32(UVCG_MAX_BITRATE_360P),
 .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_360P),
 .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_360P),
 .bFrameIntervalType = 3,
 .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_360P),
 .dwFrameInterval[1] = cpu_to_le32(UVCG_FRM_INTERV_1_360P),
 .dwFrameInterval[2] = cpu_to_le32(UVCG_FRM_INTERV_2_360P),
};

static u32 uvcg_frame_yuv_360p_dw_frame_interval[] = {
 [0] = UVCG_FRM_INTERV_0_360P,
 [1] = UVCG_FRM_INTERV_1_360P,
 [2] = UVCG_FRM_INTERV_2_360P,
};

static const struct uvcg_frame uvcg_frame_yuv_360p = {
 .fmt_type  = UVCG_UNCOMPRESSED,
 .frame = {
  .b_length   = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
  .b_descriptor_type  = USB_DT_CS_INTERFACE,
  .b_descriptor_subtype  = UVC_VS_FRAME_UNCOMPRESSED,
  .b_frame_index   = 1,
  .bm_capabilities  = 0,
  .w_width   = UVCG_WIDTH_360P,
  .w_height   = UVCG_HEIGHT_360P,
  .dw_min_bit_rate  = UVCG_MIN_BITRATE_360P,
  .dw_max_bit_rate  = UVCG_MAX_BITRATE_360P,
  .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_360P,
  .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_360P,
  .b_frame_interval_type  = 3,
 },
 .dw_frame_interval = uvcg_frame_yuv_360p_dw_frame_interval,
};

static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_360p = {
 .frm = (struct uvcg_frame *)&uvcg_frame_yuv_360p,
};
#define UVCG_WIDTH_720P   1280
#define UVCG_HEIGHT_720P  720
#define UVCG_MIN_BITRATE_720P  29491200
#define UVCG_MAX_BITRATE_720P  29491200
#define UVCG_MAX_VIDEO_FB_SZ_720P 1843200
#define UVCG_FRM_INTERV_0_720P  5000000
#define UVCG_DEFAULT_FRM_INTERV_720P UVCG_FRM_INTERV_0_720P

static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
 .bLength  = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
 .bFrameIndex  = 2,
 .bmCapabilities  = 0,
 .wWidth   = cpu_to_le16(UVCG_WIDTH_720P),
 .wHeight  = cpu_to_le16(UVCG_HEIGHT_720P),
 .dwMinBitRate  = cpu_to_le32(UVCG_MIN_BITRATE_720P),
 .dwMaxBitRate  = cpu_to_le32(UVCG_MAX_BITRATE_720P),
 .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_720P),
 .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_720P),
 .bFrameIntervalType = 1,
 .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_720P),
};

static u32 uvcg_frame_yuv_720p_dw_frame_interval[] = {
 [0] = UVCG_FRM_INTERV_0_720P,
};

static const struct uvcg_frame uvcg_frame_yuv_720p = {
 .fmt_type  = UVCG_UNCOMPRESSED,
 .frame = {
  .b_length   = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
  .b_descriptor_type  = USB_DT_CS_INTERFACE,
  .b_descriptor_subtype  = UVC_VS_FRAME_UNCOMPRESSED,
  .b_frame_index   = 2,
  .bm_capabilities  = 0,
  .w_width   = UVCG_WIDTH_720P,
  .w_height   = UVCG_HEIGHT_720P,
  .dw_min_bit_rate  = UVCG_MIN_BITRATE_720P,
  .dw_max_bit_rate  = UVCG_MAX_BITRATE_720P,
  .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_720P,
  .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_720P,
  .b_frame_interval_type  = 1,
 },
 .dw_frame_interval = uvcg_frame_yuv_720p_dw_frame_interval,
};

static struct uvcg_frame_ptr uvcg_frame_ptr_yuv_720p = {
 .frm = (struct uvcg_frame *)&uvcg_frame_yuv_720p,
};

static struct uvcg_mjpeg uvcg_format_mjpeg = {
 .fmt = {
  .type   = UVCG_MJPEG,
  /* add to .frames and fill .num_frames at runtime */
  .color_matching  = (struct uvcg_color_matching *)&uvcg_color_matching,
 },
 .desc = {
  .bLength  = UVC_DT_FORMAT_MJPEG_SIZE,
  .bDescriptorType = USB_DT_CS_INTERFACE,
  .bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
  .bFormatIndex  = 2,
  .bNumFrameDescriptors = 2,
  .bmFlags  = 0,
  .bDefaultFrameIndex = 1,
  .bAspectRatioX  = 0,
  .bAspectRatioY  = 0,
  .bmInterlaceFlags = 0,
  .bCopyProtect  = 0,
 },
};

static struct uvcg_format_ptr uvcg_format_ptr_mjpeg = {
 .fmt = &uvcg_format_mjpeg.fmt,
};

DECLARE_UVC_FRAME_MJPEG(1);
DECLARE_UVC_FRAME_MJPEG(3);

static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
 .bLength  = UVC_DT_FRAME_MJPEG_SIZE(3),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VS_FRAME_MJPEG,
 .bFrameIndex  = 1,
 .bmCapabilities  = 0,
 .wWidth   = cpu_to_le16(UVCG_WIDTH_360P),
 .wHeight  = cpu_to_le16(UVCG_HEIGHT_360P),
 .dwMinBitRate  = cpu_to_le32(UVCG_MIN_BITRATE_360P),
 .dwMaxBitRate  = cpu_to_le32(UVCG_MAX_BITRATE_360P),
 .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_360P),
 .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_360P),
 .bFrameIntervalType = 3,
 .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_360P),
 .dwFrameInterval[1] = cpu_to_le32(UVCG_FRM_INTERV_1_360P),
 .dwFrameInterval[2] = cpu_to_le32(UVCG_FRM_INTERV_2_360P),
};

static u32 uvcg_frame_mjpeg_360p_dw_frame_interval[] = {
 [0] = UVCG_FRM_INTERV_0_360P,
 [1] = UVCG_FRM_INTERV_1_360P,
 [2] = UVCG_FRM_INTERV_2_360P,
};

static const struct uvcg_frame uvcg_frame_mjpeg_360p = {
 .fmt_type  = UVCG_MJPEG,
 .frame = {
  .b_length   = UVC_DT_FRAME_MJPEG_SIZE(3),
  .b_descriptor_type  = USB_DT_CS_INTERFACE,
  .b_descriptor_subtype  = UVC_VS_FRAME_MJPEG,
  .b_frame_index   = 1,
  .bm_capabilities  = 0,
  .w_width   = UVCG_WIDTH_360P,
  .w_height   = UVCG_HEIGHT_360P,
  .dw_min_bit_rate  = UVCG_MIN_BITRATE_360P,
  .dw_max_bit_rate  = UVCG_MAX_BITRATE_360P,
  .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_360P,
  .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_360P,
  .b_frame_interval_type  = 3,
 },
 .dw_frame_interval = uvcg_frame_mjpeg_360p_dw_frame_interval,
};

static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_360p = {
 .frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_360p,
};

static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
 .bLength  = UVC_DT_FRAME_MJPEG_SIZE(1),
 .bDescriptorType = USB_DT_CS_INTERFACE,
 .bDescriptorSubType = UVC_VS_FRAME_MJPEG,
 .bFrameIndex  = 2,
 .bmCapabilities  = 0,
 .wWidth   = cpu_to_le16(UVCG_WIDTH_720P),
 .wHeight  = cpu_to_le16(UVCG_HEIGHT_720P),
 .dwMinBitRate  = cpu_to_le32(UVCG_MIN_BITRATE_720P),
 .dwMaxBitRate  = cpu_to_le32(UVCG_MAX_BITRATE_720P),
 .dwMaxVideoFrameBufferSize = cpu_to_le32(UVCG_MAX_VIDEO_FB_SZ_720P),
 .dwDefaultFrameInterval = cpu_to_le32(UVCG_DEFAULT_FRM_INTERV_720P),
 .bFrameIntervalType = 1,
 .dwFrameInterval[0] = cpu_to_le32(UVCG_FRM_INTERV_0_720P),
};

static u32 uvcg_frame_mjpeg_720p_dw_frame_interval[] = {
 [0] = UVCG_FRM_INTERV_0_720P,
};

static const struct uvcg_frame uvcg_frame_mjpeg_720p = {
 .fmt_type  = UVCG_MJPEG,
 .frame = {
  .b_length   = UVC_DT_FRAME_MJPEG_SIZE(1),
  .b_descriptor_type  = USB_DT_CS_INTERFACE,
  .b_descriptor_subtype  = UVC_VS_FRAME_MJPEG,
  .b_frame_index   = 2,
  .bm_capabilities  = 0,
  .w_width   = UVCG_WIDTH_720P,
  .w_height   = UVCG_HEIGHT_720P,
  .dw_min_bit_rate  = UVCG_MIN_BITRATE_720P,
  .dw_max_bit_rate  = UVCG_MAX_BITRATE_720P,
  .dw_max_video_frame_buffer_size = UVCG_MAX_VIDEO_FB_SZ_720P,
  .dw_default_frame_interval = UVCG_DEFAULT_FRM_INTERV_720P,
  .b_frame_interval_type  = 1,
 },
 .dw_frame_interval = uvcg_frame_mjpeg_720p_dw_frame_interval,
};

static struct uvcg_frame_ptr uvcg_frame_ptr_mjpeg_720p = {
 .frm = (struct uvcg_frame *)&uvcg_frame_mjpeg_720p,
};

static struct uvcg_streaming_header uvcg_streaming_header = {
};

static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
 (const struct uvc_descriptor_header *) &uvc_control_header,
 (const struct uvc_descriptor_header *) &uvc_camera_terminal,
 (const struct uvc_descriptor_header *) &uvc_processing,
 (const struct uvc_descriptor_header *) &uvc_output_terminal,
 NULL,
};

static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = {
 (const struct uvc_descriptor_header *) &uvc_control_header,
 (const struct uvc_descriptor_header *) &uvc_camera_terminal,
 (const struct uvc_descriptor_header *) &uvc_processing,
 (const struct uvc_descriptor_header *) &uvc_output_terminal,
 NULL,
};

static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
 (const struct uvc_descriptor_header *) &uvc_input_header,
 (const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
 (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
 (const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
 (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
 NULL,
};

static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
 (const struct uvc_descriptor_header *) &uvc_input_header,
 (const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
 (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
 (const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
 (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
 NULL,
};

static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
 (const struct uvc_descriptor_header *) &uvc_input_header,
 (const struct uvc_descriptor_header *) &uvcg_format_yuv.desc,
 (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
 (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
 (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
 (const struct uvc_descriptor_header *) &uvcg_format_mjpeg.desc,
 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
 (const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
 (const struct uvc_descriptor_header *) &uvcg_color_matching.desc,
 NULL,
};

/* --------------------------------------------------------------------------
 * USB configuration
 */


static int
webcam_config_bind(struct usb_configuration *c)
{
 int status = 0;

 f_uvc = usb_get_function(fi_uvc);
 if (IS_ERR(f_uvc))
  return PTR_ERR(f_uvc);

 status = usb_add_function(c, f_uvc);
 if (status < 0)
  usb_put_function(f_uvc);

 return status;
}

static struct usb_configuration webcam_config_driver = {
 .label   = webcam_config_label,
 .bConfigurationValue = 1,
 .iConfiguration  = 0, /* dynamic */
 .bmAttributes  = USB_CONFIG_ATT_SELFPOWER,
 .MaxPower  = CONFIG_USB_GADGET_VBUS_DRAW,
};

static int
webcam_unbind(struct usb_composite_dev *cdev)
{
 if (!IS_ERR_OR_NULL(f_uvc))
  usb_put_function(f_uvc);
 if (!IS_ERR_OR_NULL(fi_uvc))
  usb_put_function_instance(fi_uvc);
 return 0;
}

static int
webcam_bind(struct usb_composite_dev *cdev)
{
 struct f_uvc_opts *uvc_opts;
 int ret;

 fi_uvc = usb_get_function_instance("uvc");
 if (IS_ERR(fi_uvc))
  return PTR_ERR(fi_uvc);

 uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst);

 uvc_opts->streaming_interval = streaming_interval;
 uvc_opts->streaming_maxpacket = streaming_maxpacket;
 uvc_opts->streaming_maxburst = streaming_maxburst;

 uvc_opts->fs_control = uvc_fs_control_cls;
 uvc_opts->ss_control = uvc_ss_control_cls;
 uvc_opts->fs_streaming = uvc_fs_streaming_cls;
 uvc_opts->hs_streaming = uvc_hs_streaming_cls;
 uvc_opts->ss_streaming = uvc_ss_streaming_cls;

 INIT_LIST_HEAD(&uvcg_format_yuv.fmt.frames);
 list_add_tail(&uvcg_frame_ptr_yuv_360p.entry, &uvcg_format_yuv.fmt.frames);
 list_add_tail(&uvcg_frame_ptr_yuv_720p.entry, &uvcg_format_yuv.fmt.frames);
 uvcg_format_yuv.fmt.num_frames = 2;

 INIT_LIST_HEAD(&uvcg_format_mjpeg.fmt.frames);
 list_add_tail(&uvcg_frame_ptr_mjpeg_360p.entry, &uvcg_format_mjpeg.fmt.frames);
 list_add_tail(&uvcg_frame_ptr_mjpeg_720p.entry, &uvcg_format_mjpeg.fmt.frames);
 uvcg_format_mjpeg.fmt.num_frames = 2;

 INIT_LIST_HEAD(&uvcg_streaming_header.formats);
 list_add_tail(&uvcg_format_ptr_yuv.entry, &uvcg_streaming_header.formats);
 list_add_tail(&uvcg_format_ptr_mjpeg.entry, &uvcg_streaming_header.formats);
 uvcg_streaming_header.num_fmt = 2;

 uvc_opts->header = &uvcg_streaming_header;

 /* Allocate string descriptor numbers ... note that string contents
 * can be overridden by the composite_dev glue.
 */

 ret = usb_string_ids_tab(cdev, webcam_strings);
 if (ret < 0)
  goto error;
 webcam_device_descriptor.iManufacturer =
  webcam_strings[USB_GADGET_MANUFACTURER_IDX].id;
 webcam_device_descriptor.iProduct =
  webcam_strings[USB_GADGET_PRODUCT_IDX].id;
 webcam_config_driver.iConfiguration =
  webcam_strings[STRING_DESCRIPTION_IDX].id;

 /* Register our configuration. */
 if ((ret = usb_add_config(cdev, &webcam_config_driver,
     webcam_config_bind)) < 0)
  goto error;

 usb_composite_overwrite_options(cdev, &coverwrite);
 INFO(cdev, "Webcam Video Gadget\n");
 return 0;

error:
 usb_put_function_instance(fi_uvc);
 return ret;
}

/* --------------------------------------------------------------------------
 * Driver
 */


static struct usb_composite_driver webcam_driver = {
 .name  = "g_webcam",
 .dev  = &webcam_device_descriptor,
 .strings = webcam_device_strings,
 .max_speed = USB_SPEED_SUPER,
 .bind  = webcam_bind,
 .unbind  = webcam_unbind,
};

module_usb_composite_driver(webcam_driver);

MODULE_AUTHOR("Laurent Pinchart");
MODULE_DESCRIPTION("Webcam Video Gadget");
MODULE_LICENSE("GPL");


Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.