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