Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *	webcam.c -- USB webcam gadget driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *	Copyright (C) 2009-2010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *	    Laurent Pinchart (laurent.pinchart@ideasonboard.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/usb/video.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "u_uvc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) USB_GADGET_COMPOSITE_OPTIONS();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) /* module parameters specific to the Video streaming endpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) static unsigned int streaming_interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) MODULE_PARM_DESC(streaming_interval, "1 - 16");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static unsigned int streaming_maxpacket = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) static unsigned int streaming_maxburst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * Device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define WEBCAM_VENDOR_ID		0x1d6b	/* Linux Foundation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define WEBCAM_PRODUCT_ID		0x0102	/* Webcam A/V gadget */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define WEBCAM_DEVICE_BCD		0x0010	/* 0.10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static char webcam_vendor_label[] = "Linux Foundation";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) static char webcam_product_label[] = "Webcam gadget";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static char webcam_config_label[] = "Video";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) /* string IDs are assigned dynamically */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define STRING_DESCRIPTION_IDX		USB_GADGET_FIRST_AVAIL_IDX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) static struct usb_string webcam_strings[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	[USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	[USB_GADGET_PRODUCT_IDX].s = webcam_product_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	[USB_GADGET_SERIAL_IDX].s = "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	[STRING_DESCRIPTION_IDX].s = webcam_config_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	{  }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) static struct usb_gadget_strings webcam_stringtab = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	.language = 0x0409,	/* en-us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	.strings = webcam_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static struct usb_gadget_strings *webcam_device_strings[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	&webcam_stringtab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static struct usb_function_instance *fi_uvc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static struct usb_function *f_uvc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static struct usb_device_descriptor webcam_device_descriptor = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	.bLength		= USB_DT_DEVICE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	.bDescriptorType	= USB_DT_DEVICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	/* .bcdUSB = DYNAMIC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	.bDeviceClass		= USB_CLASS_MISC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	.bDeviceSubClass	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	.bDeviceProtocol	= 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	.bMaxPacketSize0	= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	.idVendor		= cpu_to_le16(WEBCAM_VENDOR_ID),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	.idProduct		= cpu_to_le16(WEBCAM_PRODUCT_ID),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	.bcdDevice		= cpu_to_le16(WEBCAM_DEVICE_BCD),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	.iManufacturer		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	.iProduct		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	.iSerialNumber		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	.bNumConfigurations	= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) DECLARE_UVC_HEADER_DESCRIPTOR(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	.bLength		= UVC_DT_HEADER_SIZE(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	.bDescriptorSubType	= UVC_VC_HEADER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	.bcdUVC			= cpu_to_le16(0x0100),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	.wTotalLength		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	.dwClockFrequency	= cpu_to_le32(48000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	.bInCollection		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	.baInterfaceNr[0]	= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	.bLength		= UVC_DT_CAMERA_TERMINAL_SIZE(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	.bDescriptorSubType	= UVC_VC_INPUT_TERMINAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	.bTerminalID		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	.wTerminalType		= cpu_to_le16(0x0201),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	.bAssocTerminal		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	.iTerminal		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	.wObjectiveFocalLengthMin	= cpu_to_le16(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	.wObjectiveFocalLengthMax	= cpu_to_le16(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	.wOcularFocalLength		= cpu_to_le16(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	.bControlSize		= 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	.bmControls[0]		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	.bmControls[1]		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	.bmControls[2]		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static const struct uvc_processing_unit_descriptor uvc_processing = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	.bLength		= UVC_DT_PROCESSING_UNIT_SIZE(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	.bDescriptorSubType	= UVC_VC_PROCESSING_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	.bUnitID		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	.bSourceID		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	.wMaxMultiplier		= cpu_to_le16(16*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	.bControlSize		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	.bmControls[0]		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	.bmControls[1]		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	.iProcessing		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	.bmVideoStandards	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	.bLength		= UVC_DT_OUTPUT_TERMINAL_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	.bDescriptorSubType	= UVC_VC_OUTPUT_TERMINAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	.bTerminalID		= 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	.wTerminalType		= cpu_to_le16(0x0101),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	.bAssocTerminal		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	.bSourceID		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	.iTerminal		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	.bLength		= UVC_DT_INPUT_HEADER_SIZE(1, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	.bDescriptorSubType	= UVC_VS_INPUT_HEADER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	.bNumFormats		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	.wTotalLength		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	.bEndpointAddress	= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	.bmInfo			= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	.bTerminalLink		= 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	.bStillCaptureMethod	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	.bTriggerSupport	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	.bTriggerUsage		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	.bControlSize		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	.bmaControls[0][0]	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	.bmaControls[1][0]	= 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static const struct uvc_format_uncompressed uvc_format_yuv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	.bLength		= UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	.bDescriptorSubType	= UVC_VS_FORMAT_UNCOMPRESSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	.bFormatIndex		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	.bNumFrameDescriptors	= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	.guidFormat		=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	.bBitsPerPixel		= 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	.bDefaultFrameIndex	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	.bAspectRatioX		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	.bAspectRatioY		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	.bmInterfaceFlags	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	.bCopyProtect		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) DECLARE_UVC_FRAME_UNCOMPRESSED(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) DECLARE_UVC_FRAME_UNCOMPRESSED(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	.bFrameIndex		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	.bmCapabilities		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	.wWidth			= cpu_to_le16(640),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	.wHeight		= cpu_to_le16(360),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	.dwMinBitRate		= cpu_to_le32(18432000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	.dwMaxBitRate		= cpu_to_le32(55296000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	.dwMaxVideoFrameBufferSize	= cpu_to_le32(460800),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	.dwDefaultFrameInterval	= cpu_to_le32(666666),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	.bFrameIntervalType	= 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	.dwFrameInterval[0]	= cpu_to_le32(666666),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	.dwFrameInterval[1]	= cpu_to_le32(1000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	.dwFrameInterval[2]	= cpu_to_le32(5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	.bLength		= UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	.bDescriptorSubType	= UVC_VS_FRAME_UNCOMPRESSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	.bFrameIndex		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	.bmCapabilities		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	.wWidth			= cpu_to_le16(1280),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	.wHeight		= cpu_to_le16(720),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	.dwMinBitRate		= cpu_to_le32(29491200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	.dwMaxBitRate		= cpu_to_le32(29491200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	.dwMaxVideoFrameBufferSize	= cpu_to_le32(1843200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	.dwDefaultFrameInterval	= cpu_to_le32(5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	.bFrameIntervalType	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	.dwFrameInterval[0]	= cpu_to_le32(5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static const struct uvc_format_mjpeg uvc_format_mjpg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	.bLength		= UVC_DT_FORMAT_MJPEG_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	.bDescriptorSubType	= UVC_VS_FORMAT_MJPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	.bFormatIndex		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	.bNumFrameDescriptors	= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	.bmFlags		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	.bDefaultFrameIndex	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	.bAspectRatioX		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	.bAspectRatioY		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	.bmInterfaceFlags	= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	.bCopyProtect		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) DECLARE_UVC_FRAME_MJPEG(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) DECLARE_UVC_FRAME_MJPEG(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	.bFrameIndex		= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	.bmCapabilities		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	.wWidth			= cpu_to_le16(640),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	.wHeight		= cpu_to_le16(360),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	.dwMinBitRate		= cpu_to_le32(18432000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	.dwMaxBitRate		= cpu_to_le32(55296000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	.dwMaxVideoFrameBufferSize	= cpu_to_le32(460800),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	.dwDefaultFrameInterval	= cpu_to_le32(666666),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	.bFrameIntervalType	= 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	.dwFrameInterval[0]	= cpu_to_le32(666666),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	.dwFrameInterval[1]	= cpu_to_le32(1000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	.dwFrameInterval[2]	= cpu_to_le32(5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	.bLength		= UVC_DT_FRAME_MJPEG_SIZE(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	.bDescriptorSubType	= UVC_VS_FRAME_MJPEG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	.bFrameIndex		= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	.bmCapabilities		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	.wWidth			= cpu_to_le16(1280),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	.wHeight		= cpu_to_le16(720),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	.dwMinBitRate		= cpu_to_le32(29491200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	.dwMaxBitRate		= cpu_to_le32(29491200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	.dwMaxVideoFrameBufferSize	= cpu_to_le32(1843200),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	.dwDefaultFrameInterval	= cpu_to_le32(5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	.bFrameIntervalType	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	.dwFrameInterval[0]	= cpu_to_le32(5000000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static const struct uvc_color_matching_descriptor uvc_color_matching = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	.bLength		= UVC_DT_COLOR_MATCHING_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	.bDescriptorType	= USB_DT_CS_INTERFACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	.bDescriptorSubType	= UVC_VS_COLORFORMAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	.bColorPrimaries	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	.bTransferCharacteristics	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	.bMatrixCoefficients	= 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	(const struct uvc_descriptor_header *) &uvc_control_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	(const struct uvc_descriptor_header *) &uvc_processing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	(const struct uvc_descriptor_header *) &uvc_output_terminal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	(const struct uvc_descriptor_header *) &uvc_control_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	(const struct uvc_descriptor_header *) &uvc_camera_terminal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	(const struct uvc_descriptor_header *) &uvc_processing,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	(const struct uvc_descriptor_header *) &uvc_output_terminal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	(const struct uvc_descriptor_header *) &uvc_input_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	(const struct uvc_descriptor_header *) &uvc_format_yuv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	(const struct uvc_descriptor_header *) &uvc_format_mjpg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	(const struct uvc_descriptor_header *) &uvc_color_matching,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	(const struct uvc_descriptor_header *) &uvc_input_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	(const struct uvc_descriptor_header *) &uvc_format_yuv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	(const struct uvc_descriptor_header *) &uvc_format_mjpg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	(const struct uvc_descriptor_header *) &uvc_color_matching,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	(const struct uvc_descriptor_header *) &uvc_input_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	(const struct uvc_descriptor_header *) &uvc_format_yuv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	(const struct uvc_descriptor_header *) &uvc_format_mjpg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	(const struct uvc_descriptor_header *) &uvc_color_matching,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  * USB configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) webcam_config_bind(struct usb_configuration *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	f_uvc = usb_get_function(fi_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	if (IS_ERR(f_uvc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		return PTR_ERR(f_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	status = usb_add_function(c, f_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (status < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		usb_put_function(f_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static struct usb_configuration webcam_config_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	.label			= webcam_config_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	.bConfigurationValue	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	.iConfiguration		= 0, /* dynamic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	.MaxPower		= CONFIG_USB_GADGET_VBUS_DRAW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) webcam_unbind(struct usb_composite_dev *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	if (!IS_ERR_OR_NULL(f_uvc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		usb_put_function(f_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	if (!IS_ERR_OR_NULL(fi_uvc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		usb_put_function_instance(fi_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) webcam_bind(struct usb_composite_dev *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	struct f_uvc_opts *uvc_opts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	fi_uvc = usb_get_function_instance("uvc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	if (IS_ERR(fi_uvc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 		return PTR_ERR(fi_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	uvc_opts = container_of(fi_uvc, struct f_uvc_opts, func_inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	uvc_opts->streaming_interval = streaming_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	uvc_opts->streaming_maxpacket = streaming_maxpacket;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	uvc_opts->streaming_maxburst = streaming_maxburst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	uvc_opts->fs_control = uvc_fs_control_cls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	uvc_opts->ss_control = uvc_ss_control_cls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	uvc_opts->fs_streaming = uvc_fs_streaming_cls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	uvc_opts->hs_streaming = uvc_hs_streaming_cls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	uvc_opts->ss_streaming = uvc_ss_streaming_cls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	uvc_opts->pm_qos_latency = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	/* Allocate string descriptor numbers ... note that string contents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	 * can be overridden by the composite_dev glue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	ret = usb_string_ids_tab(cdev, webcam_strings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	webcam_device_descriptor.iManufacturer =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		webcam_strings[USB_GADGET_MANUFACTURER_IDX].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	webcam_device_descriptor.iProduct =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		webcam_strings[USB_GADGET_PRODUCT_IDX].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	webcam_config_driver.iConfiguration =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		webcam_strings[STRING_DESCRIPTION_IDX].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	/* Register our configuration. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	if ((ret = usb_add_config(cdev, &webcam_config_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 					webcam_config_bind)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	usb_composite_overwrite_options(cdev, &coverwrite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	INFO(cdev, "Webcam Video Gadget\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	usb_put_function_instance(fi_uvc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)  * Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static struct usb_composite_driver webcam_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	.name		= "g_webcam",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	.dev		= &webcam_device_descriptor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	.strings	= webcam_device_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	.max_speed	= USB_SPEED_SUPER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	.bind		= webcam_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	.unbind		= webcam_unbind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) module_usb_composite_driver(webcam_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) MODULE_AUTHOR("Laurent Pinchart");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) MODULE_DESCRIPTION("Webcam Video Gadget");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)