• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * uvc_configfs.c
3  *
4  * Configfs support for the uvc function.
5  *
6  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
7  *		http://www.samsung.com
8  *
9  * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 #include "u_uvc.h"
16 #include "uvc_configfs.h"
17 
18 #define UVCG_STREAMING_CONTROL_SIZE	1
19 
20 #define UVC_ATTR(prefix, cname, aname) \
21 static struct configfs_attribute prefix##attr_##cname = { \
22 	.ca_name	= __stringify(aname),				\
23 	.ca_mode	= S_IRUGO | S_IWUGO,				\
24 	.ca_owner	= THIS_MODULE,					\
25 	.show		= prefix##cname##_show,				\
26 	.store		= prefix##cname##_store,			\
27 }
28 
29 #define UVC_ATTR_RO(prefix, cname, aname) \
30 static struct configfs_attribute prefix##attr_##cname = { \
31 	.ca_name	= __stringify(aname),				\
32 	.ca_mode	= S_IRUGO,					\
33 	.ca_owner	= THIS_MODULE,					\
34 	.show		= prefix##cname##_show,				\
35 }
36 
37 static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item);
38 
39 /* control/header/<NAME> */
40 DECLARE_UVC_HEADER_DESCRIPTOR(1);
41 
42 struct uvcg_control_header {
43 	struct config_item		item;
44 	struct UVC_HEADER_DESCRIPTOR(1)	desc;
45 	unsigned			linked;
46 };
47 
to_uvcg_control_header(struct config_item * item)48 static struct uvcg_control_header *to_uvcg_control_header(struct config_item *item)
49 {
50 	return container_of(item, struct uvcg_control_header, item);
51 }
52 
53 #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit)	\
54 static ssize_t uvcg_control_header_##cname##_show(			\
55 	struct config_item *item, char *page)			\
56 {									\
57 	struct uvcg_control_header *ch = to_uvcg_control_header(item);	\
58 	struct f_uvc_opts *opts;					\
59 	struct config_item *opts_item;					\
60 	struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
61 	int result;							\
62 									\
63 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
64 									\
65 	opts_item = ch->item.ci_parent->ci_parent->ci_parent;		\
66 	opts = to_f_uvc_opts(opts_item);				\
67 									\
68 	mutex_lock(&opts->lock);					\
69 	result = sprintf(page, "%d\n", conv(ch->desc.aname));		\
70 	mutex_unlock(&opts->lock);					\
71 									\
72 	mutex_unlock(su_mutex);						\
73 	return result;							\
74 }									\
75 									\
76 static ssize_t								\
77 uvcg_control_header_##cname##_store(struct config_item *item,		\
78 			   const char *page, size_t len)		\
79 {									\
80 	struct uvcg_control_header *ch = to_uvcg_control_header(item);	\
81 	struct f_uvc_opts *opts;					\
82 	struct config_item *opts_item;					\
83 	struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
84 	int ret;							\
85 	uxx num;							\
86 									\
87 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
88 									\
89 	opts_item = ch->item.ci_parent->ci_parent->ci_parent;		\
90 	opts = to_f_uvc_opts(opts_item);				\
91 									\
92 	mutex_lock(&opts->lock);					\
93 	if (ch->linked || opts->refcnt) {				\
94 		ret = -EBUSY;						\
95 		goto end;						\
96 	}								\
97 									\
98 	ret = str2u(page, 0, &num);					\
99 	if (ret)							\
100 		goto end;						\
101 									\
102 	if (num > limit) {						\
103 		ret = -EINVAL;						\
104 		goto end;						\
105 	}								\
106 	ch->desc.aname = vnoc(num);					\
107 	ret = len;							\
108 end:									\
109 	mutex_unlock(&opts->lock);					\
110 	mutex_unlock(su_mutex);						\
111 	return ret;							\
112 }									\
113 									\
114 UVC_ATTR(uvcg_control_header_, cname, aname)
115 
116 UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
117 		   0xffff);
118 
119 UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32,
120 		   u32, cpu_to_le32, 0x7fffffff);
121 
122 #undef UVCG_CTRL_HDR_ATTR
123 
124 static struct configfs_attribute *uvcg_control_header_attrs[] = {
125 	&uvcg_control_header_attr_bcd_uvc,
126 	&uvcg_control_header_attr_dw_clock_frequency,
127 	NULL,
128 };
129 
130 static struct config_item_type uvcg_control_header_type = {
131 	.ct_attrs	= uvcg_control_header_attrs,
132 	.ct_owner	= THIS_MODULE,
133 };
134 
uvcg_control_header_make(struct config_group * group,const char * name)135 static struct config_item *uvcg_control_header_make(struct config_group *group,
136 						    const char *name)
137 {
138 	struct uvcg_control_header *h;
139 
140 	h = kzalloc(sizeof(*h), GFP_KERNEL);
141 	if (!h)
142 		return ERR_PTR(-ENOMEM);
143 
144 	h->desc.bLength			= UVC_DT_HEADER_SIZE(1);
145 	h->desc.bDescriptorType		= USB_DT_CS_INTERFACE;
146 	h->desc.bDescriptorSubType	= UVC_VC_HEADER;
147 	h->desc.bcdUVC			= cpu_to_le16(0x0100);
148 	h->desc.dwClockFrequency	= cpu_to_le32(48000000);
149 
150 	config_item_init_type_name(&h->item, name, &uvcg_control_header_type);
151 
152 	return &h->item;
153 }
154 
uvcg_control_header_drop(struct config_group * group,struct config_item * item)155 static void uvcg_control_header_drop(struct config_group *group,
156 			      struct config_item *item)
157 {
158 	struct uvcg_control_header *h = to_uvcg_control_header(item);
159 
160 	kfree(h);
161 }
162 
163 /* control/header */
164 static struct uvcg_control_header_grp {
165 	struct config_group	group;
166 } uvcg_control_header_grp;
167 
168 static struct configfs_group_operations uvcg_control_header_grp_ops = {
169 	.make_item		= uvcg_control_header_make,
170 	.drop_item		= uvcg_control_header_drop,
171 };
172 
173 static struct config_item_type uvcg_control_header_grp_type = {
174 	.ct_group_ops	= &uvcg_control_header_grp_ops,
175 	.ct_owner	= THIS_MODULE,
176 };
177 
178 /* control/processing/default */
179 static struct uvcg_default_processing {
180 	struct config_group	group;
181 } uvcg_default_processing;
182 
183 static inline struct uvcg_default_processing
to_uvcg_default_processing(struct config_item * item)184 *to_uvcg_default_processing(struct config_item *item)
185 {
186 	return container_of(to_config_group(item),
187 			    struct uvcg_default_processing, group);
188 }
189 
190 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv)		\
191 static ssize_t uvcg_default_processing_##cname##_show(			\
192 	struct config_item *item, char *page)				\
193 {									\
194 	struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
195 	struct f_uvc_opts *opts;					\
196 	struct config_item *opts_item;					\
197 	struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;	\
198 	struct uvc_processing_unit_descriptor *pd;			\
199 	int result;							\
200 									\
201 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
202 									\
203 	opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;	\
204 	opts = to_f_uvc_opts(opts_item);				\
205 	pd = &opts->uvc_processing;					\
206 									\
207 	mutex_lock(&opts->lock);					\
208 	result = sprintf(page, "%d\n", conv(pd->aname));		\
209 	mutex_unlock(&opts->lock);					\
210 									\
211 	mutex_unlock(su_mutex);						\
212 	return result;							\
213 }									\
214 									\
215 UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
216 
217 #define identity_conv(x) (x)
218 
219 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, identity_conv);
220 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, identity_conv);
221 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, le16_to_cpu);
222 UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv);
223 
224 #undef identity_conv
225 
226 #undef UVCG_DEFAULT_PROCESSING_ATTR
227 
uvcg_default_processing_bm_controls_show(struct config_item * item,char * page)228 static ssize_t uvcg_default_processing_bm_controls_show(
229 	struct config_item *item, char *page)
230 {
231 	struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
232 	struct f_uvc_opts *opts;
233 	struct config_item *opts_item;
234 	struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
235 	struct uvc_processing_unit_descriptor *pd;
236 	int result, i;
237 	char *pg = page;
238 
239 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
240 
241 	opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
242 	opts = to_f_uvc_opts(opts_item);
243 	pd = &opts->uvc_processing;
244 
245 	mutex_lock(&opts->lock);
246 	for (result = 0, i = 0; i < pd->bControlSize; ++i) {
247 		result += sprintf(pg, "%d\n", pd->bmControls[i]);
248 		pg = page + result;
249 	}
250 	mutex_unlock(&opts->lock);
251 
252 	mutex_unlock(su_mutex);
253 
254 	return result;
255 }
256 
257 UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
258 
259 static struct configfs_attribute *uvcg_default_processing_attrs[] = {
260 	&uvcg_default_processing_attr_b_unit_id,
261 	&uvcg_default_processing_attr_b_source_id,
262 	&uvcg_default_processing_attr_w_max_multiplier,
263 	&uvcg_default_processing_attr_bm_controls,
264 	&uvcg_default_processing_attr_i_processing,
265 	NULL,
266 };
267 
268 static struct config_item_type uvcg_default_processing_type = {
269 	.ct_attrs	= uvcg_default_processing_attrs,
270 	.ct_owner	= THIS_MODULE,
271 };
272 
273 /* struct uvcg_processing {}; */
274 
275 static struct config_group *uvcg_processing_default_groups[] = {
276 	&uvcg_default_processing.group,
277 	NULL,
278 };
279 
280 /* control/processing */
281 static struct uvcg_processing_grp {
282 	struct config_group	group;
283 } uvcg_processing_grp;
284 
285 static struct config_item_type uvcg_processing_grp_type = {
286 	.ct_owner = THIS_MODULE,
287 };
288 
289 /* control/terminal/camera/default */
290 static struct uvcg_default_camera {
291 	struct config_group	group;
292 } uvcg_default_camera;
293 
294 static inline struct uvcg_default_camera
to_uvcg_default_camera(struct config_item * item)295 *to_uvcg_default_camera(struct config_item *item)
296 {
297 	return container_of(to_config_group(item),
298 			    struct uvcg_default_camera, group);
299 }
300 
301 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv)			\
302 static ssize_t uvcg_default_camera_##cname##_show(			\
303 	struct config_item *item, char *page)				\
304 {									\
305 	struct uvcg_default_camera *dc = to_uvcg_default_camera(item);	\
306 	struct f_uvc_opts *opts;					\
307 	struct config_item *opts_item;					\
308 	struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;	\
309 	struct uvc_camera_terminal_descriptor *cd;			\
310 	int result;							\
311 									\
312 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
313 									\
314 	opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent->	\
315 			ci_parent;					\
316 	opts = to_f_uvc_opts(opts_item);				\
317 	cd = &opts->uvc_camera_terminal;				\
318 									\
319 	mutex_lock(&opts->lock);					\
320 	result = sprintf(page, "%d\n", conv(cd->aname));		\
321 	mutex_unlock(&opts->lock);					\
322 									\
323 	mutex_unlock(su_mutex);						\
324 									\
325 	return result;							\
326 }									\
327 									\
328 UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
329 
330 #define identity_conv(x) (x)
331 
332 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, identity_conv);
333 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, le16_to_cpu);
334 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv);
335 UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, identity_conv);
336 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
337 			 le16_to_cpu);
338 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
339 			 le16_to_cpu);
340 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
341 			 le16_to_cpu);
342 
343 #undef identity_conv
344 
345 #undef UVCG_DEFAULT_CAMERA_ATTR
346 
uvcg_default_camera_bm_controls_show(struct config_item * item,char * page)347 static ssize_t uvcg_default_camera_bm_controls_show(
348 	struct config_item *item, char *page)
349 {
350 	struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
351 	struct f_uvc_opts *opts;
352 	struct config_item *opts_item;
353 	struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
354 	struct uvc_camera_terminal_descriptor *cd;
355 	int result, i;
356 	char *pg = page;
357 
358 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
359 
360 	opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent->
361 			ci_parent;
362 	opts = to_f_uvc_opts(opts_item);
363 	cd = &opts->uvc_camera_terminal;
364 
365 	mutex_lock(&opts->lock);
366 	for (result = 0, i = 0; i < cd->bControlSize; ++i) {
367 		result += sprintf(pg, "%d\n", cd->bmControls[i]);
368 		pg = page + result;
369 	}
370 	mutex_unlock(&opts->lock);
371 
372 	mutex_unlock(su_mutex);
373 	return result;
374 }
375 
376 UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
377 
378 static struct configfs_attribute *uvcg_default_camera_attrs[] = {
379 	&uvcg_default_camera_attr_b_terminal_id,
380 	&uvcg_default_camera_attr_w_terminal_type,
381 	&uvcg_default_camera_attr_b_assoc_terminal,
382 	&uvcg_default_camera_attr_i_terminal,
383 	&uvcg_default_camera_attr_w_objective_focal_length_min,
384 	&uvcg_default_camera_attr_w_objective_focal_length_max,
385 	&uvcg_default_camera_attr_w_ocular_focal_length,
386 	&uvcg_default_camera_attr_bm_controls,
387 	NULL,
388 };
389 
390 static struct config_item_type uvcg_default_camera_type = {
391 	.ct_attrs	= uvcg_default_camera_attrs,
392 	.ct_owner	= THIS_MODULE,
393 };
394 
395 /* struct uvcg_camera {}; */
396 
397 static struct config_group *uvcg_camera_default_groups[] = {
398 	&uvcg_default_camera.group,
399 	NULL,
400 };
401 
402 /* control/terminal/camera */
403 static struct uvcg_camera_grp {
404 	struct config_group	group;
405 } uvcg_camera_grp;
406 
407 static struct config_item_type uvcg_camera_grp_type = {
408 	.ct_owner = THIS_MODULE,
409 };
410 
411 /* control/terminal/output/default */
412 static struct uvcg_default_output {
413 	struct config_group	group;
414 } uvcg_default_output;
415 
416 static inline struct uvcg_default_output
to_uvcg_default_output(struct config_item * item)417 *to_uvcg_default_output(struct config_item *item)
418 {
419 	return container_of(to_config_group(item),
420 			    struct uvcg_default_output, group);
421 }
422 
423 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv)			\
424 static ssize_t uvcg_default_output_##cname##_show(			\
425 	struct config_item *item, char *page)			\
426 {									\
427 	struct uvcg_default_output *dout = to_uvcg_default_output(item); \
428 	struct f_uvc_opts *opts;					\
429 	struct config_item *opts_item;					\
430 	struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex;	\
431 	struct uvc_output_terminal_descriptor *cd;			\
432 	int result;							\
433 									\
434 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
435 									\
436 	opts_item = dout->group.cg_item.ci_parent->ci_parent->		\
437 			ci_parent->ci_parent;				\
438 	opts = to_f_uvc_opts(opts_item);				\
439 	cd = &opts->uvc_output_terminal;				\
440 									\
441 	mutex_lock(&opts->lock);					\
442 	result = sprintf(page, "%d\n", conv(cd->aname));		\
443 	mutex_unlock(&opts->lock);					\
444 									\
445 	mutex_unlock(su_mutex);						\
446 									\
447 	return result;							\
448 }									\
449 									\
450 UVC_ATTR_RO(uvcg_default_output_, cname, aname)
451 
452 #define identity_conv(x) (x)
453 
454 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, identity_conv);
455 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, le16_to_cpu);
456 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv);
457 UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, identity_conv);
458 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv);
459 
460 #undef identity_conv
461 
462 #undef UVCG_DEFAULT_OUTPUT_ATTR
463 
464 static struct configfs_attribute *uvcg_default_output_attrs[] = {
465 	&uvcg_default_output_attr_b_terminal_id,
466 	&uvcg_default_output_attr_w_terminal_type,
467 	&uvcg_default_output_attr_b_assoc_terminal,
468 	&uvcg_default_output_attr_b_source_id,
469 	&uvcg_default_output_attr_i_terminal,
470 	NULL,
471 };
472 
473 static struct config_item_type uvcg_default_output_type = {
474 	.ct_attrs	= uvcg_default_output_attrs,
475 	.ct_owner	= THIS_MODULE,
476 };
477 
478 /* struct uvcg_output {}; */
479 
480 static struct config_group *uvcg_output_default_groups[] = {
481 	&uvcg_default_output.group,
482 	NULL,
483 };
484 
485 /* control/terminal/output */
486 static struct uvcg_output_grp {
487 	struct config_group	group;
488 } uvcg_output_grp;
489 
490 static struct config_item_type uvcg_output_grp_type = {
491 	.ct_owner = THIS_MODULE,
492 };
493 
494 static struct config_group *uvcg_terminal_default_groups[] = {
495 	&uvcg_camera_grp.group,
496 	&uvcg_output_grp.group,
497 	NULL,
498 };
499 
500 /* control/terminal */
501 static struct uvcg_terminal_grp {
502 	struct config_group	group;
503 } uvcg_terminal_grp;
504 
505 static struct config_item_type uvcg_terminal_grp_type = {
506 	.ct_owner = THIS_MODULE,
507 };
508 
509 /* control/class/{fs} */
510 static struct uvcg_control_class {
511 	struct config_group	group;
512 } uvcg_control_class_fs, uvcg_control_class_ss;
513 
514 
515 static inline struct uvc_descriptor_header
uvcg_get_ctl_class_arr(struct config_item * i,struct f_uvc_opts * o)516 **uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
517 {
518 	struct uvcg_control_class *cl = container_of(to_config_group(i),
519 		struct uvcg_control_class, group);
520 
521 	if (cl == &uvcg_control_class_fs)
522 		return o->uvc_fs_control_cls;
523 
524 	if (cl == &uvcg_control_class_ss)
525 		return o->uvc_ss_control_cls;
526 
527 	return NULL;
528 }
529 
uvcg_control_class_allow_link(struct config_item * src,struct config_item * target)530 static int uvcg_control_class_allow_link(struct config_item *src,
531 					 struct config_item *target)
532 {
533 	struct config_item *control, *header;
534 	struct f_uvc_opts *opts;
535 	struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
536 	struct uvc_descriptor_header **class_array;
537 	struct uvcg_control_header *target_hdr;
538 	int ret = -EINVAL;
539 
540 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
541 
542 	control = src->ci_parent->ci_parent;
543 	header = config_group_find_item(to_config_group(control), "header");
544 	if (!header || target->ci_parent != header)
545 		goto out;
546 
547 	opts = to_f_uvc_opts(control->ci_parent);
548 
549 	mutex_lock(&opts->lock);
550 
551 	class_array = uvcg_get_ctl_class_arr(src, opts);
552 	if (!class_array)
553 		goto unlock;
554 	if (opts->refcnt || class_array[0]) {
555 		ret = -EBUSY;
556 		goto unlock;
557 	}
558 
559 	target_hdr = to_uvcg_control_header(target);
560 	++target_hdr->linked;
561 	class_array[0] = (struct uvc_descriptor_header *)&target_hdr->desc;
562 	ret = 0;
563 
564 unlock:
565 	mutex_unlock(&opts->lock);
566 out:
567 	config_item_put(header);
568 	mutex_unlock(su_mutex);
569 	return ret;
570 }
571 
uvcg_control_class_drop_link(struct config_item * src,struct config_item * target)572 static int uvcg_control_class_drop_link(struct config_item *src,
573 					struct config_item *target)
574 {
575 	struct config_item *control, *header;
576 	struct f_uvc_opts *opts;
577 	struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
578 	struct uvc_descriptor_header **class_array;
579 	struct uvcg_control_header *target_hdr;
580 	int ret = -EINVAL;
581 
582 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
583 
584 	control = src->ci_parent->ci_parent;
585 	header = config_group_find_item(to_config_group(control), "header");
586 	if (!header || target->ci_parent != header)
587 		goto out;
588 
589 	opts = to_f_uvc_opts(control->ci_parent);
590 
591 	mutex_lock(&opts->lock);
592 
593 	class_array = uvcg_get_ctl_class_arr(src, opts);
594 	if (!class_array)
595 		goto unlock;
596 	if (opts->refcnt) {
597 		ret = -EBUSY;
598 		goto unlock;
599 	}
600 
601 	target_hdr = to_uvcg_control_header(target);
602 	--target_hdr->linked;
603 	class_array[0] = NULL;
604 	ret = 0;
605 
606 unlock:
607 	mutex_unlock(&opts->lock);
608 out:
609 	config_item_put(header);
610 	mutex_unlock(su_mutex);
611 	return ret;
612 }
613 
614 static struct configfs_item_operations uvcg_control_class_item_ops = {
615 	.allow_link	= uvcg_control_class_allow_link,
616 	.drop_link	= uvcg_control_class_drop_link,
617 };
618 
619 static struct config_item_type uvcg_control_class_type = {
620 	.ct_item_ops	= &uvcg_control_class_item_ops,
621 	.ct_owner	= THIS_MODULE,
622 };
623 
624 static struct config_group *uvcg_control_class_default_groups[] = {
625 	&uvcg_control_class_fs.group,
626 	&uvcg_control_class_ss.group,
627 	NULL,
628 };
629 
630 /* control/class */
631 static struct uvcg_control_class_grp {
632 	struct config_group	group;
633 } uvcg_control_class_grp;
634 
635 static struct config_item_type uvcg_control_class_grp_type = {
636 	.ct_owner = THIS_MODULE,
637 };
638 
639 static struct config_group *uvcg_control_default_groups[] = {
640 	&uvcg_control_header_grp.group,
641 	&uvcg_processing_grp.group,
642 	&uvcg_terminal_grp.group,
643 	&uvcg_control_class_grp.group,
644 	NULL,
645 };
646 
647 /* control */
648 static struct uvcg_control_grp {
649 	struct config_group	group;
650 } uvcg_control_grp;
651 
652 static struct config_item_type uvcg_control_grp_type = {
653 	.ct_owner = THIS_MODULE,
654 };
655 
656 /* streaming/uncompressed */
657 static struct uvcg_uncompressed_grp {
658 	struct config_group	group;
659 } uvcg_uncompressed_grp;
660 
661 /* streaming/mjpeg */
662 static struct uvcg_mjpeg_grp {
663 	struct config_group	group;
664 } uvcg_mjpeg_grp;
665 
666 static struct config_item *fmt_parent[] = {
667 	&uvcg_uncompressed_grp.group.cg_item,
668 	&uvcg_mjpeg_grp.group.cg_item,
669 };
670 
671 enum uvcg_format_type {
672 	UVCG_UNCOMPRESSED = 0,
673 	UVCG_MJPEG,
674 };
675 
676 struct uvcg_format {
677 	struct config_group	group;
678 	enum uvcg_format_type	type;
679 	unsigned		linked;
680 	unsigned		num_frames;
681 	__u8			bmaControls[UVCG_STREAMING_CONTROL_SIZE];
682 };
683 
to_uvcg_format(struct config_item * item)684 static struct uvcg_format *to_uvcg_format(struct config_item *item)
685 {
686 	return container_of(to_config_group(item), struct uvcg_format, group);
687 }
688 
uvcg_format_bma_controls_show(struct uvcg_format * f,char * page)689 static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
690 {
691 	struct f_uvc_opts *opts;
692 	struct config_item *opts_item;
693 	struct mutex *su_mutex = &f->group.cg_subsys->su_mutex;
694 	int result, i;
695 	char *pg = page;
696 
697 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
698 
699 	opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
700 	opts = to_f_uvc_opts(opts_item);
701 
702 	mutex_lock(&opts->lock);
703 	result = sprintf(pg, "0x");
704 	pg += result;
705 	for (i = 0; i < UVCG_STREAMING_CONTROL_SIZE; ++i) {
706 		result += sprintf(pg, "%x\n", f->bmaControls[i]);
707 		pg = page + result;
708 	}
709 	mutex_unlock(&opts->lock);
710 
711 	mutex_unlock(su_mutex);
712 	return result;
713 }
714 
uvcg_format_bma_controls_store(struct uvcg_format * ch,const char * page,size_t len)715 static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
716 					      const char *page, size_t len)
717 {
718 	struct f_uvc_opts *opts;
719 	struct config_item *opts_item;
720 	struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex;
721 	int ret = -EINVAL;
722 
723 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
724 
725 	opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent;
726 	opts = to_f_uvc_opts(opts_item);
727 
728 	mutex_lock(&opts->lock);
729 	if (ch->linked || opts->refcnt) {
730 		ret = -EBUSY;
731 		goto end;
732 	}
733 
734 	if (len < 4 || *page != '0' ||
735 	    (*(page + 1) != 'x' && *(page + 1) != 'X'))
736 		goto end;
737 	ret = hex2bin(ch->bmaControls, page + 2, 1);
738 	if (ret < 0)
739 		goto end;
740 	ret = len;
741 end:
742 	mutex_unlock(&opts->lock);
743 	mutex_unlock(su_mutex);
744 	return ret;
745 }
746 
747 struct uvcg_format_ptr {
748 	struct uvcg_format	*fmt;
749 	struct list_head	entry;
750 };
751 
752 /* streaming/header/<NAME> */
753 struct uvcg_streaming_header {
754 	struct config_item				item;
755 	struct uvc_input_header_descriptor		desc;
756 	unsigned					linked;
757 	struct list_head				formats;
758 	unsigned					num_fmt;
759 };
760 
to_uvcg_streaming_header(struct config_item * item)761 static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item *item)
762 {
763 	return container_of(item, struct uvcg_streaming_header, item);
764 }
765 
uvcg_streaming_header_allow_link(struct config_item * src,struct config_item * target)766 static int uvcg_streaming_header_allow_link(struct config_item *src,
767 					    struct config_item *target)
768 {
769 	struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
770 	struct config_item *opts_item;
771 	struct f_uvc_opts *opts;
772 	struct uvcg_streaming_header *src_hdr;
773 	struct uvcg_format *target_fmt = NULL;
774 	struct uvcg_format_ptr *format_ptr;
775 	int i, ret = -EINVAL;
776 
777 	src_hdr = to_uvcg_streaming_header(src);
778 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
779 
780 	opts_item = src->ci_parent->ci_parent->ci_parent;
781 	opts = to_f_uvc_opts(opts_item);
782 
783 	mutex_lock(&opts->lock);
784 
785 	if (src_hdr->linked) {
786 		ret = -EBUSY;
787 		goto out;
788 	}
789 
790 	for (i = 0; i < ARRAY_SIZE(fmt_parent); ++i)
791 		if (target->ci_parent == fmt_parent[i])
792 			break;
793 	if (i == ARRAY_SIZE(fmt_parent))
794 		goto out;
795 
796 	target_fmt = container_of(to_config_group(target), struct uvcg_format,
797 				  group);
798 	if (!target_fmt)
799 		goto out;
800 
801 	format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
802 	if (!format_ptr) {
803 		ret = -ENOMEM;
804 		goto out;
805 	}
806 	ret = 0;
807 	format_ptr->fmt = target_fmt;
808 	list_add_tail(&format_ptr->entry, &src_hdr->formats);
809 	++src_hdr->num_fmt;
810 	++target_fmt->linked;
811 
812 out:
813 	mutex_unlock(&opts->lock);
814 	mutex_unlock(su_mutex);
815 	return ret;
816 }
817 
uvcg_streaming_header_drop_link(struct config_item * src,struct config_item * target)818 static int uvcg_streaming_header_drop_link(struct config_item *src,
819 					   struct config_item *target)
820 {
821 	struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
822 	struct config_item *opts_item;
823 	struct f_uvc_opts *opts;
824 	struct uvcg_streaming_header *src_hdr;
825 	struct uvcg_format *target_fmt = NULL;
826 	struct uvcg_format_ptr *format_ptr, *tmp;
827 	int ret = -EINVAL;
828 
829 	src_hdr = to_uvcg_streaming_header(src);
830 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
831 
832 	opts_item = src->ci_parent->ci_parent->ci_parent;
833 	opts = to_f_uvc_opts(opts_item);
834 
835 	mutex_lock(&opts->lock);
836 	target_fmt = container_of(to_config_group(target), struct uvcg_format,
837 				  group);
838 	if (!target_fmt)
839 		goto out;
840 
841 	list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
842 		if (format_ptr->fmt == target_fmt) {
843 			list_del(&format_ptr->entry);
844 			kfree(format_ptr);
845 			--src_hdr->num_fmt;
846 			break;
847 		}
848 
849 	--target_fmt->linked;
850 
851 out:
852 	mutex_unlock(&opts->lock);
853 	mutex_unlock(su_mutex);
854 	return ret;
855 
856 }
857 
858 static struct configfs_item_operations uvcg_streaming_header_item_ops = {
859 	.allow_link		= uvcg_streaming_header_allow_link,
860 	.drop_link		= uvcg_streaming_header_drop_link,
861 };
862 
863 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv)			\
864 static ssize_t uvcg_streaming_header_##cname##_show(			\
865 	struct config_item *item, char *page)			\
866 {									\
867 	struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
868 	struct f_uvc_opts *opts;					\
869 	struct config_item *opts_item;					\
870 	struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
871 	int result;							\
872 									\
873 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
874 									\
875 	opts_item = sh->item.ci_parent->ci_parent->ci_parent;		\
876 	opts = to_f_uvc_opts(opts_item);				\
877 									\
878 	mutex_lock(&opts->lock);					\
879 	result = sprintf(page, "%d\n", conv(sh->desc.aname));		\
880 	mutex_unlock(&opts->lock);					\
881 									\
882 	mutex_unlock(su_mutex);						\
883 	return result;							\
884 }									\
885 									\
886 UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
887 
888 #define identity_conv(x) (x)
889 
890 UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, identity_conv);
891 UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, identity_conv);
892 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod,
893 			   identity_conv);
894 UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, identity_conv);
895 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv);
896 
897 #undef identity_conv
898 
899 #undef UVCG_STREAMING_HEADER_ATTR
900 
901 static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
902 	&uvcg_streaming_header_attr_bm_info,
903 	&uvcg_streaming_header_attr_b_terminal_link,
904 	&uvcg_streaming_header_attr_b_still_capture_method,
905 	&uvcg_streaming_header_attr_b_trigger_support,
906 	&uvcg_streaming_header_attr_b_trigger_usage,
907 	NULL,
908 };
909 
910 static struct config_item_type uvcg_streaming_header_type = {
911 	.ct_item_ops	= &uvcg_streaming_header_item_ops,
912 	.ct_attrs	= uvcg_streaming_header_attrs,
913 	.ct_owner	= THIS_MODULE,
914 };
915 
916 static struct config_item
uvcg_streaming_header_make(struct config_group * group,const char * name)917 *uvcg_streaming_header_make(struct config_group *group, const char *name)
918 {
919 	struct uvcg_streaming_header *h;
920 
921 	h = kzalloc(sizeof(*h), GFP_KERNEL);
922 	if (!h)
923 		return ERR_PTR(-ENOMEM);
924 
925 	INIT_LIST_HEAD(&h->formats);
926 	h->desc.bDescriptorType		= USB_DT_CS_INTERFACE;
927 	h->desc.bDescriptorSubType	= UVC_VS_INPUT_HEADER;
928 	h->desc.bTerminalLink		= 3;
929 	h->desc.bControlSize		= UVCG_STREAMING_CONTROL_SIZE;
930 
931 	config_item_init_type_name(&h->item, name, &uvcg_streaming_header_type);
932 
933 	return &h->item;
934 }
935 
uvcg_streaming_header_drop(struct config_group * group,struct config_item * item)936 static void uvcg_streaming_header_drop(struct config_group *group,
937 			      struct config_item *item)
938 {
939 	struct uvcg_streaming_header *h = to_uvcg_streaming_header(item);
940 
941 	kfree(h);
942 }
943 
944 /* streaming/header */
945 static struct uvcg_streaming_header_grp {
946 	struct config_group	group;
947 } uvcg_streaming_header_grp;
948 
949 static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
950 	.make_item		= uvcg_streaming_header_make,
951 	.drop_item		= uvcg_streaming_header_drop,
952 };
953 
954 static struct config_item_type uvcg_streaming_header_grp_type = {
955 	.ct_group_ops	= &uvcg_streaming_header_grp_ops,
956 	.ct_owner	= THIS_MODULE,
957 };
958 
959 /* streaming/<mode>/<format>/<NAME> */
960 struct uvcg_frame {
961 	struct {
962 		u8	b_length;
963 		u8	b_descriptor_type;
964 		u8	b_descriptor_subtype;
965 		u8	b_frame_index;
966 		u8	bm_capabilities;
967 		u16	w_width;
968 		u16	w_height;
969 		u32	dw_min_bit_rate;
970 		u32	dw_max_bit_rate;
971 		u32	dw_max_video_frame_buffer_size;
972 		u32	dw_default_frame_interval;
973 		u8	b_frame_interval_type;
974 	} __attribute__((packed)) frame;
975 	u32 *dw_frame_interval;
976 	enum uvcg_format_type	fmt_type;
977 	struct config_item	item;
978 };
979 
to_uvcg_frame(struct config_item * item)980 static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
981 {
982 	return container_of(item, struct uvcg_frame, item);
983 }
984 
985 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
986 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
987 {									\
988 	struct uvcg_frame *f = to_uvcg_frame(item);			\
989 	struct f_uvc_opts *opts;					\
990 	struct config_item *opts_item;					\
991 	struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
992 	int result;							\
993 									\
994 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
995 									\
996 	opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent;	\
997 	opts = to_f_uvc_opts(opts_item);				\
998 									\
999 	mutex_lock(&opts->lock);					\
1000 	result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname));	\
1001 	mutex_unlock(&opts->lock);					\
1002 									\
1003 	mutex_unlock(su_mutex);						\
1004 	return result;							\
1005 }									\
1006 									\
1007 static ssize_t  uvcg_frame_##cname##_store(struct config_item *item,	\
1008 					   const char *page, size_t len)\
1009 {									\
1010 	struct uvcg_frame *f = to_uvcg_frame(item);			\
1011 	struct f_uvc_opts *opts;					\
1012 	struct config_item *opts_item;					\
1013 	struct uvcg_format *fmt;					\
1014 	struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1015 	int ret;							\
1016 	u##bits num;							\
1017 									\
1018 	ret = kstrtou##bits(page, 0, &num);				\
1019 	if (ret)							\
1020 		return ret;						\
1021 									\
1022 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1023 									\
1024 	opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent;	\
1025 	opts = to_f_uvc_opts(opts_item);				\
1026 	fmt = to_uvcg_format(f->item.ci_parent);			\
1027 									\
1028 	mutex_lock(&opts->lock);					\
1029 	if (fmt->linked || opts->refcnt) {				\
1030 		ret = -EBUSY;						\
1031 		goto end;						\
1032 	}								\
1033 									\
1034 	f->frame.cname = to_little_endian(num);				\
1035 	ret = len;							\
1036 end:									\
1037 	mutex_unlock(&opts->lock);					\
1038 	mutex_unlock(su_mutex);						\
1039 	return ret;							\
1040 }									\
1041 									\
1042 UVC_ATTR(uvcg_frame_, cname, aname);
1043 
1044 #define noop_conversion(x) (x)
1045 
1046 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
1047 		noop_conversion, 8);
1048 UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
1049 UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
1050 UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32);
1051 UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32);
1052 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize,
1053 		le32_to_cpu, cpu_to_le32, 32);
1054 UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
1055 		le32_to_cpu, cpu_to_le32, 32);
1056 
1057 #undef noop_conversion
1058 
1059 #undef UVCG_FRAME_ATTR
1060 
uvcg_frame_dw_frame_interval_show(struct config_item * item,char * page)1061 static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
1062 						 char *page)
1063 {
1064 	struct uvcg_frame *frm = to_uvcg_frame(item);
1065 	struct f_uvc_opts *opts;
1066 	struct config_item *opts_item;
1067 	struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
1068 	int result, i;
1069 	char *pg = page;
1070 
1071 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1072 
1073 	opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
1074 	opts = to_f_uvc_opts(opts_item);
1075 
1076 	mutex_lock(&opts->lock);
1077 	for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
1078 		result += sprintf(pg, "%d\n",
1079 				  le32_to_cpu(frm->dw_frame_interval[i]));
1080 		pg = page + result;
1081 	}
1082 	mutex_unlock(&opts->lock);
1083 
1084 	mutex_unlock(su_mutex);
1085 	return result;
1086 }
1087 
__uvcg_count_frm_intrv(char * buf,void * priv)1088 static inline int __uvcg_count_frm_intrv(char *buf, void *priv)
1089 {
1090 	++*((int *)priv);
1091 	return 0;
1092 }
1093 
__uvcg_fill_frm_intrv(char * buf,void * priv)1094 static inline int __uvcg_fill_frm_intrv(char *buf, void *priv)
1095 {
1096 	u32 num, **interv;
1097 	int ret;
1098 
1099 	ret = kstrtou32(buf, 0, &num);
1100 	if (ret)
1101 		return ret;
1102 
1103 	interv = priv;
1104 	**interv = cpu_to_le32(num);
1105 	++*interv;
1106 
1107 	return 0;
1108 }
1109 
__uvcg_iter_frm_intrv(const char * page,size_t len,int (* fun)(char *,void *),void * priv)1110 static int __uvcg_iter_frm_intrv(const char *page, size_t len,
1111 				 int (*fun)(char *, void *), void *priv)
1112 {
1113 	/* sign, base 2 representation, newline, terminator */
1114 	char buf[1 + sizeof(u32) * 8 + 1 + 1];
1115 	const char *pg = page;
1116 	int i, ret;
1117 
1118 	if (!fun)
1119 		return -EINVAL;
1120 
1121 	while (pg - page < len) {
1122 		i = 0;
1123 		while (i < sizeof(buf) && (pg - page < len) &&
1124 				*pg != '\0' && *pg != '\n')
1125 			buf[i++] = *pg++;
1126 		if (i == sizeof(buf))
1127 			return -EINVAL;
1128 		while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
1129 			++pg;
1130 		buf[i] = '\0';
1131 		ret = fun(buf, priv);
1132 		if (ret)
1133 			return ret;
1134 	}
1135 
1136 	return 0;
1137 }
1138 
uvcg_frame_dw_frame_interval_store(struct config_item * item,const char * page,size_t len)1139 static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
1140 						  const char *page, size_t len)
1141 {
1142 	struct uvcg_frame *ch = to_uvcg_frame(item);
1143 	struct f_uvc_opts *opts;
1144 	struct config_item *opts_item;
1145 	struct uvcg_format *fmt;
1146 	struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
1147 	int ret = 0, n = 0;
1148 	u32 *frm_intrv, *tmp;
1149 
1150 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1151 
1152 	opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
1153 	opts = to_f_uvc_opts(opts_item);
1154 	fmt = to_uvcg_format(ch->item.ci_parent);
1155 
1156 	mutex_lock(&opts->lock);
1157 	if (fmt->linked || opts->refcnt) {
1158 		ret = -EBUSY;
1159 		goto end;
1160 	}
1161 
1162 	ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n);
1163 	if (ret)
1164 		goto end;
1165 
1166 	tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL);
1167 	if (!frm_intrv) {
1168 		ret = -ENOMEM;
1169 		goto end;
1170 	}
1171 
1172 	ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp);
1173 	if (ret) {
1174 		kfree(frm_intrv);
1175 		goto end;
1176 	}
1177 
1178 	kfree(ch->dw_frame_interval);
1179 	ch->dw_frame_interval = frm_intrv;
1180 	ch->frame.b_frame_interval_type = n;
1181 	ret = len;
1182 
1183 end:
1184 	mutex_unlock(&opts->lock);
1185 	mutex_unlock(su_mutex);
1186 	return ret;
1187 }
1188 
1189 UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
1190 
1191 static struct configfs_attribute *uvcg_frame_attrs[] = {
1192 	&uvcg_frame_attr_bm_capabilities,
1193 	&uvcg_frame_attr_w_width,
1194 	&uvcg_frame_attr_w_height,
1195 	&uvcg_frame_attr_dw_min_bit_rate,
1196 	&uvcg_frame_attr_dw_max_bit_rate,
1197 	&uvcg_frame_attr_dw_max_video_frame_buffer_size,
1198 	&uvcg_frame_attr_dw_default_frame_interval,
1199 	&uvcg_frame_attr_dw_frame_interval,
1200 	NULL,
1201 };
1202 
1203 static struct config_item_type uvcg_frame_type = {
1204 	.ct_attrs	= uvcg_frame_attrs,
1205 	.ct_owner	= THIS_MODULE,
1206 };
1207 
uvcg_frame_make(struct config_group * group,const char * name)1208 static struct config_item *uvcg_frame_make(struct config_group *group,
1209 					   const char *name)
1210 {
1211 	struct uvcg_frame *h;
1212 	struct uvcg_format *fmt;
1213 	struct f_uvc_opts *opts;
1214 	struct config_item *opts_item;
1215 
1216 	h = kzalloc(sizeof(*h), GFP_KERNEL);
1217 	if (!h)
1218 		return ERR_PTR(-ENOMEM);
1219 
1220 	h->frame.b_descriptor_type		= USB_DT_CS_INTERFACE;
1221 	h->frame.b_frame_index			= 1;
1222 	h->frame.w_width			= cpu_to_le16(640);
1223 	h->frame.w_height			= cpu_to_le16(360);
1224 	h->frame.dw_min_bit_rate		= cpu_to_le32(18432000);
1225 	h->frame.dw_max_bit_rate		= cpu_to_le32(55296000);
1226 	h->frame.dw_max_video_frame_buffer_size	= cpu_to_le32(460800);
1227 	h->frame.dw_default_frame_interval	= cpu_to_le32(666666);
1228 
1229 	opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1230 	opts = to_f_uvc_opts(opts_item);
1231 
1232 	mutex_lock(&opts->lock);
1233 	fmt = to_uvcg_format(&group->cg_item);
1234 	if (fmt->type == UVCG_UNCOMPRESSED) {
1235 		h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED;
1236 		h->fmt_type = UVCG_UNCOMPRESSED;
1237 	} else if (fmt->type == UVCG_MJPEG) {
1238 		h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
1239 		h->fmt_type = UVCG_MJPEG;
1240 	} else {
1241 		mutex_unlock(&opts->lock);
1242 		kfree(h);
1243 		return ERR_PTR(-EINVAL);
1244 	}
1245 	++fmt->num_frames;
1246 	mutex_unlock(&opts->lock);
1247 
1248 	config_item_init_type_name(&h->item, name, &uvcg_frame_type);
1249 
1250 	return &h->item;
1251 }
1252 
uvcg_frame_drop(struct config_group * group,struct config_item * item)1253 static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
1254 {
1255 	struct uvcg_frame *h = to_uvcg_frame(item);
1256 	struct uvcg_format *fmt;
1257 	struct f_uvc_opts *opts;
1258 	struct config_item *opts_item;
1259 
1260 	opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1261 	opts = to_f_uvc_opts(opts_item);
1262 
1263 	mutex_lock(&opts->lock);
1264 	fmt = to_uvcg_format(&group->cg_item);
1265 	--fmt->num_frames;
1266 	kfree(h);
1267 	mutex_unlock(&opts->lock);
1268 }
1269 
1270 /* streaming/uncompressed/<NAME> */
1271 struct uvcg_uncompressed {
1272 	struct uvcg_format		fmt;
1273 	struct uvc_format_uncompressed	desc;
1274 };
1275 
to_uvcg_uncompressed(struct config_item * item)1276 static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item)
1277 {
1278 	return container_of(
1279 		container_of(to_config_group(item), struct uvcg_format, group),
1280 		struct uvcg_uncompressed, fmt);
1281 }
1282 
1283 static struct configfs_group_operations uvcg_uncompressed_group_ops = {
1284 	.make_item		= uvcg_frame_make,
1285 	.drop_item		= uvcg_frame_drop,
1286 };
1287 
uvcg_uncompressed_guid_format_show(struct config_item * item,char * page)1288 static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
1289 							char *page)
1290 {
1291 	struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1292 	struct f_uvc_opts *opts;
1293 	struct config_item *opts_item;
1294 	struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1295 
1296 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1297 
1298 	opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1299 	opts = to_f_uvc_opts(opts_item);
1300 
1301 	mutex_lock(&opts->lock);
1302 	memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
1303 	mutex_unlock(&opts->lock);
1304 
1305 	mutex_unlock(su_mutex);
1306 
1307 	return sizeof(ch->desc.guidFormat);
1308 }
1309 
uvcg_uncompressed_guid_format_store(struct config_item * item,const char * page,size_t len)1310 static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
1311 						   const char *page, size_t len)
1312 {
1313 	struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1314 	struct f_uvc_opts *opts;
1315 	struct config_item *opts_item;
1316 	struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1317 	int ret;
1318 
1319 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1320 
1321 	opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1322 	opts = to_f_uvc_opts(opts_item);
1323 
1324 	mutex_lock(&opts->lock);
1325 	if (ch->fmt.linked || opts->refcnt) {
1326 		ret = -EBUSY;
1327 		goto end;
1328 	}
1329 
1330 	memcpy(ch->desc.guidFormat, page,
1331 	       min(sizeof(ch->desc.guidFormat), len));
1332 	ret = sizeof(ch->desc.guidFormat);
1333 
1334 end:
1335 	mutex_unlock(&opts->lock);
1336 	mutex_unlock(su_mutex);
1337 	return ret;
1338 }
1339 
1340 UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
1341 
1342 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv)			\
1343 static ssize_t uvcg_uncompressed_##cname##_show(			\
1344 	struct config_item *item, char *page)				\
1345 {									\
1346 	struct uvcg_uncompressed *u = to_uvcg_uncompressed(item);	\
1347 	struct f_uvc_opts *opts;					\
1348 	struct config_item *opts_item;					\
1349 	struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;	\
1350 	int result;							\
1351 									\
1352 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1353 									\
1354 	opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1355 	opts = to_f_uvc_opts(opts_item);				\
1356 									\
1357 	mutex_lock(&opts->lock);					\
1358 	result = sprintf(page, "%d\n", conv(u->desc.aname));		\
1359 	mutex_unlock(&opts->lock);					\
1360 									\
1361 	mutex_unlock(su_mutex);						\
1362 	return result;							\
1363 }									\
1364 									\
1365 UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
1366 
1367 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv)			\
1368 static ssize_t uvcg_uncompressed_##cname##_show(			\
1369 	struct config_item *item, char *page)				\
1370 {									\
1371 	struct uvcg_uncompressed *u = to_uvcg_uncompressed(item);	\
1372 	struct f_uvc_opts *opts;					\
1373 	struct config_item *opts_item;					\
1374 	struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;	\
1375 	int result;							\
1376 									\
1377 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1378 									\
1379 	opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1380 	opts = to_f_uvc_opts(opts_item);				\
1381 									\
1382 	mutex_lock(&opts->lock);					\
1383 	result = sprintf(page, "%d\n", conv(u->desc.aname));		\
1384 	mutex_unlock(&opts->lock);					\
1385 									\
1386 	mutex_unlock(su_mutex);						\
1387 	return result;							\
1388 }									\
1389 									\
1390 static ssize_t								\
1391 uvcg_uncompressed_##cname##_store(struct config_item *item,		\
1392 				    const char *page, size_t len)	\
1393 {									\
1394 	struct uvcg_uncompressed *u = to_uvcg_uncompressed(item);	\
1395 	struct f_uvc_opts *opts;					\
1396 	struct config_item *opts_item;					\
1397 	struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;	\
1398 	int ret;							\
1399 	u8 num;								\
1400 									\
1401 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1402 									\
1403 	opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1404 	opts = to_f_uvc_opts(opts_item);				\
1405 									\
1406 	mutex_lock(&opts->lock);					\
1407 	if (u->fmt.linked || opts->refcnt) {				\
1408 		ret = -EBUSY;						\
1409 		goto end;						\
1410 	}								\
1411 									\
1412 	ret = kstrtou8(page, 0, &num);					\
1413 	if (ret)							\
1414 		goto end;						\
1415 									\
1416 	if (num > 255) {						\
1417 		ret = -EINVAL;						\
1418 		goto end;						\
1419 	}								\
1420 	u->desc.aname = num;						\
1421 	ret = len;							\
1422 end:									\
1423 	mutex_unlock(&opts->lock);					\
1424 	mutex_unlock(su_mutex);						\
1425 	return ret;							\
1426 }									\
1427 									\
1428 UVC_ATTR(uvcg_uncompressed_, cname, aname);
1429 
1430 #define identity_conv(x) (x)
1431 
1432 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv);
1433 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex,
1434 		       identity_conv);
1435 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
1436 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
1437 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
1438 
1439 #undef identity_conv
1440 
1441 #undef UVCG_UNCOMPRESSED_ATTR
1442 #undef UVCG_UNCOMPRESSED_ATTR_RO
1443 
1444 static inline ssize_t
uvcg_uncompressed_bma_controls_show(struct config_item * item,char * page)1445 uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
1446 {
1447 	struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1448 	return uvcg_format_bma_controls_show(&unc->fmt, page);
1449 }
1450 
1451 static inline ssize_t
uvcg_uncompressed_bma_controls_store(struct config_item * item,const char * page,size_t len)1452 uvcg_uncompressed_bma_controls_store(struct config_item *item,
1453 				     const char *page, size_t len)
1454 {
1455 	struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1456 	return uvcg_format_bma_controls_store(&unc->fmt, page, len);
1457 }
1458 
1459 UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
1460 
1461 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
1462 	&uvcg_uncompressed_attr_guid_format,
1463 	&uvcg_uncompressed_attr_b_bits_per_pixel,
1464 	&uvcg_uncompressed_attr_b_default_frame_index,
1465 	&uvcg_uncompressed_attr_b_aspect_ratio_x,
1466 	&uvcg_uncompressed_attr_b_aspect_ratio_y,
1467 	&uvcg_uncompressed_attr_bm_interface_flags,
1468 	&uvcg_uncompressed_attr_bma_controls,
1469 	NULL,
1470 };
1471 
1472 static struct config_item_type uvcg_uncompressed_type = {
1473 	.ct_group_ops	= &uvcg_uncompressed_group_ops,
1474 	.ct_attrs	= uvcg_uncompressed_attrs,
1475 	.ct_owner	= THIS_MODULE,
1476 };
1477 
uvcg_uncompressed_make(struct config_group * group,const char * name)1478 static struct config_group *uvcg_uncompressed_make(struct config_group *group,
1479 						   const char *name)
1480 {
1481 	static char guid[] = {
1482 		'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00,
1483 		 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1484 	};
1485 	struct uvcg_uncompressed *h;
1486 
1487 	h = kzalloc(sizeof(*h), GFP_KERNEL);
1488 	if (!h)
1489 		return ERR_PTR(-ENOMEM);
1490 
1491 	h->desc.bLength			= UVC_DT_FORMAT_UNCOMPRESSED_SIZE;
1492 	h->desc.bDescriptorType		= USB_DT_CS_INTERFACE;
1493 	h->desc.bDescriptorSubType	= UVC_VS_FORMAT_UNCOMPRESSED;
1494 	memcpy(h->desc.guidFormat, guid, sizeof(guid));
1495 	h->desc.bBitsPerPixel		= 16;
1496 	h->desc.bDefaultFrameIndex	= 1;
1497 	h->desc.bAspectRatioX		= 0;
1498 	h->desc.bAspectRatioY		= 0;
1499 	h->desc.bmInterfaceFlags	= 0;
1500 	h->desc.bCopyProtect		= 0;
1501 
1502 	h->fmt.type = UVCG_UNCOMPRESSED;
1503 	config_group_init_type_name(&h->fmt.group, name,
1504 				    &uvcg_uncompressed_type);
1505 
1506 	return &h->fmt.group;
1507 }
1508 
uvcg_uncompressed_drop(struct config_group * group,struct config_item * item)1509 static void uvcg_uncompressed_drop(struct config_group *group,
1510 			    struct config_item *item)
1511 {
1512 	struct uvcg_uncompressed *h = to_uvcg_uncompressed(item);
1513 
1514 	kfree(h);
1515 }
1516 
1517 static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
1518 	.make_group		= uvcg_uncompressed_make,
1519 	.drop_item		= uvcg_uncompressed_drop,
1520 };
1521 
1522 static struct config_item_type uvcg_uncompressed_grp_type = {
1523 	.ct_group_ops	= &uvcg_uncompressed_grp_ops,
1524 	.ct_owner	= THIS_MODULE,
1525 };
1526 
1527 /* streaming/mjpeg/<NAME> */
1528 struct uvcg_mjpeg {
1529 	struct uvcg_format		fmt;
1530 	struct uvc_format_mjpeg		desc;
1531 };
1532 
to_uvcg_mjpeg(struct config_item * item)1533 static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
1534 {
1535 	return container_of(
1536 		container_of(to_config_group(item), struct uvcg_format, group),
1537 		struct uvcg_mjpeg, fmt);
1538 }
1539 
1540 static struct configfs_group_operations uvcg_mjpeg_group_ops = {
1541 	.make_item		= uvcg_frame_make,
1542 	.drop_item		= uvcg_frame_drop,
1543 };
1544 
1545 #define UVCG_MJPEG_ATTR_RO(cname, aname, conv)				\
1546 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1547 {									\
1548 	struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);			\
1549 	struct f_uvc_opts *opts;					\
1550 	struct config_item *opts_item;					\
1551 	struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;	\
1552 	int result;							\
1553 									\
1554 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1555 									\
1556 	opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1557 	opts = to_f_uvc_opts(opts_item);				\
1558 									\
1559 	mutex_lock(&opts->lock);					\
1560 	result = sprintf(page, "%d\n", conv(u->desc.aname));		\
1561 	mutex_unlock(&opts->lock);					\
1562 									\
1563 	mutex_unlock(su_mutex);						\
1564 	return result;							\
1565 }									\
1566 									\
1567 UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
1568 
1569 #define UVCG_MJPEG_ATTR(cname, aname, conv)				\
1570 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1571 {									\
1572 	struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);			\
1573 	struct f_uvc_opts *opts;					\
1574 	struct config_item *opts_item;					\
1575 	struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;	\
1576 	int result;							\
1577 									\
1578 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1579 									\
1580 	opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1581 	opts = to_f_uvc_opts(opts_item);				\
1582 									\
1583 	mutex_lock(&opts->lock);					\
1584 	result = sprintf(page, "%d\n", conv(u->desc.aname));		\
1585 	mutex_unlock(&opts->lock);					\
1586 									\
1587 	mutex_unlock(su_mutex);						\
1588 	return result;							\
1589 }									\
1590 									\
1591 static ssize_t								\
1592 uvcg_mjpeg_##cname##_store(struct config_item *item,			\
1593 			   const char *page, size_t len)		\
1594 {									\
1595 	struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);			\
1596 	struct f_uvc_opts *opts;					\
1597 	struct config_item *opts_item;					\
1598 	struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex;	\
1599 	int ret;							\
1600 	u8 num;								\
1601 									\
1602 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1603 									\
1604 	opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1605 	opts = to_f_uvc_opts(opts_item);				\
1606 									\
1607 	mutex_lock(&opts->lock);					\
1608 	if (u->fmt.linked || opts->refcnt) {				\
1609 		ret = -EBUSY;						\
1610 		goto end;						\
1611 	}								\
1612 									\
1613 	ret = kstrtou8(page, 0, &num);					\
1614 	if (ret)							\
1615 		goto end;						\
1616 									\
1617 	if (num > 255) {						\
1618 		ret = -EINVAL;						\
1619 		goto end;						\
1620 	}								\
1621 	u->desc.aname = num;						\
1622 	ret = len;							\
1623 end:									\
1624 	mutex_unlock(&opts->lock);					\
1625 	mutex_unlock(su_mutex);						\
1626 	return ret;							\
1627 }									\
1628 									\
1629 UVC_ATTR(uvcg_mjpeg_, cname, aname)
1630 
1631 #define identity_conv(x) (x)
1632 
1633 UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex,
1634 		       identity_conv);
1635 UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv);
1636 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
1637 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
1638 UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
1639 
1640 #undef identity_conv
1641 
1642 #undef UVCG_MJPEG_ATTR
1643 #undef UVCG_MJPEG_ATTR_RO
1644 
1645 static inline ssize_t
uvcg_mjpeg_bma_controls_show(struct config_item * item,char * page)1646 uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
1647 {
1648 	struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1649 	return uvcg_format_bma_controls_show(&u->fmt, page);
1650 }
1651 
1652 static inline ssize_t
uvcg_mjpeg_bma_controls_store(struct config_item * item,const char * page,size_t len)1653 uvcg_mjpeg_bma_controls_store(struct config_item *item,
1654 				     const char *page, size_t len)
1655 {
1656 	struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1657 	return uvcg_format_bma_controls_store(&u->fmt, page, len);
1658 }
1659 
1660 UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
1661 
1662 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
1663 	&uvcg_mjpeg_attr_b_default_frame_index,
1664 	&uvcg_mjpeg_attr_bm_flags,
1665 	&uvcg_mjpeg_attr_b_aspect_ratio_x,
1666 	&uvcg_mjpeg_attr_b_aspect_ratio_y,
1667 	&uvcg_mjpeg_attr_bm_interface_flags,
1668 	&uvcg_mjpeg_attr_bma_controls,
1669 	NULL,
1670 };
1671 
1672 static struct config_item_type uvcg_mjpeg_type = {
1673 	.ct_group_ops	= &uvcg_mjpeg_group_ops,
1674 	.ct_attrs	= uvcg_mjpeg_attrs,
1675 	.ct_owner	= THIS_MODULE,
1676 };
1677 
uvcg_mjpeg_make(struct config_group * group,const char * name)1678 static struct config_group *uvcg_mjpeg_make(struct config_group *group,
1679 						   const char *name)
1680 {
1681 	struct uvcg_mjpeg *h;
1682 
1683 	h = kzalloc(sizeof(*h), GFP_KERNEL);
1684 	if (!h)
1685 		return ERR_PTR(-ENOMEM);
1686 
1687 	h->desc.bLength			= UVC_DT_FORMAT_MJPEG_SIZE;
1688 	h->desc.bDescriptorType		= USB_DT_CS_INTERFACE;
1689 	h->desc.bDescriptorSubType	= UVC_VS_FORMAT_MJPEG;
1690 	h->desc.bDefaultFrameIndex	= 1;
1691 	h->desc.bAspectRatioX		= 0;
1692 	h->desc.bAspectRatioY		= 0;
1693 	h->desc.bmInterfaceFlags	= 0;
1694 	h->desc.bCopyProtect		= 0;
1695 
1696 	h->fmt.type = UVCG_MJPEG;
1697 	config_group_init_type_name(&h->fmt.group, name,
1698 				    &uvcg_mjpeg_type);
1699 
1700 	return &h->fmt.group;
1701 }
1702 
uvcg_mjpeg_drop(struct config_group * group,struct config_item * item)1703 static void uvcg_mjpeg_drop(struct config_group *group,
1704 			    struct config_item *item)
1705 {
1706 	struct uvcg_mjpeg *h = to_uvcg_mjpeg(item);
1707 
1708 	kfree(h);
1709 }
1710 
1711 static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
1712 	.make_group		= uvcg_mjpeg_make,
1713 	.drop_item		= uvcg_mjpeg_drop,
1714 };
1715 
1716 static struct config_item_type uvcg_mjpeg_grp_type = {
1717 	.ct_group_ops	= &uvcg_mjpeg_grp_ops,
1718 	.ct_owner	= THIS_MODULE,
1719 };
1720 
1721 /* streaming/color_matching/default */
1722 static struct uvcg_default_color_matching {
1723 	struct config_group	group;
1724 } uvcg_default_color_matching;
1725 
1726 static inline struct uvcg_default_color_matching
to_uvcg_default_color_matching(struct config_item * item)1727 *to_uvcg_default_color_matching(struct config_item *item)
1728 {
1729 	return container_of(to_config_group(item),
1730 			    struct uvcg_default_color_matching, group);
1731 }
1732 
1733 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv)		\
1734 static ssize_t uvcg_default_color_matching_##cname##_show(		\
1735 	struct config_item *item, char *page)		\
1736 {									\
1737 	struct uvcg_default_color_matching *dc =			\
1738 		to_uvcg_default_color_matching(item);			\
1739 	struct f_uvc_opts *opts;					\
1740 	struct config_item *opts_item;					\
1741 	struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;	\
1742 	struct uvc_color_matching_descriptor *cd;			\
1743 	int result;							\
1744 									\
1745 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */	\
1746 									\
1747 	opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent;	\
1748 	opts = to_f_uvc_opts(opts_item);				\
1749 	cd = &opts->uvc_color_matching;					\
1750 									\
1751 	mutex_lock(&opts->lock);					\
1752 	result = sprintf(page, "%d\n", conv(cd->aname));		\
1753 	mutex_unlock(&opts->lock);					\
1754 									\
1755 	mutex_unlock(su_mutex);						\
1756 	return result;							\
1757 }									\
1758 									\
1759 UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
1760 
1761 #define identity_conv(x) (x)
1762 
1763 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries,
1764 				 identity_conv);
1765 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics,
1766 				 bTransferCharacteristics, identity_conv);
1767 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients,
1768 				 identity_conv);
1769 
1770 #undef identity_conv
1771 
1772 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1773 
1774 static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
1775 	&uvcg_default_color_matching_attr_b_color_primaries,
1776 	&uvcg_default_color_matching_attr_b_transfer_characteristics,
1777 	&uvcg_default_color_matching_attr_b_matrix_coefficients,
1778 	NULL,
1779 };
1780 
1781 static struct config_item_type uvcg_default_color_matching_type = {
1782 	.ct_attrs	= uvcg_default_color_matching_attrs,
1783 	.ct_owner	= THIS_MODULE,
1784 };
1785 
1786 /* struct uvcg_color_matching {}; */
1787 
1788 static struct config_group *uvcg_color_matching_default_groups[] = {
1789 	&uvcg_default_color_matching.group,
1790 	NULL,
1791 };
1792 
1793 /* streaming/color_matching */
1794 static struct uvcg_color_matching_grp {
1795 	struct config_group	group;
1796 } uvcg_color_matching_grp;
1797 
1798 static struct config_item_type uvcg_color_matching_grp_type = {
1799 	.ct_owner = THIS_MODULE,
1800 };
1801 
1802 /* streaming/class/{fs|hs|ss} */
1803 static struct uvcg_streaming_class {
1804 	struct config_group	group;
1805 } uvcg_streaming_class_fs, uvcg_streaming_class_hs, uvcg_streaming_class_ss;
1806 
1807 
1808 static inline struct uvc_descriptor_header
__uvcg_get_stream_class_arr(struct config_item * i,struct f_uvc_opts * o)1809 ***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
1810 {
1811 	struct uvcg_streaming_class *cl = container_of(to_config_group(i),
1812 		struct uvcg_streaming_class, group);
1813 
1814 	if (cl == &uvcg_streaming_class_fs)
1815 		return &o->uvc_fs_streaming_cls;
1816 
1817 	if (cl == &uvcg_streaming_class_hs)
1818 		return &o->uvc_hs_streaming_cls;
1819 
1820 	if (cl == &uvcg_streaming_class_ss)
1821 		return &o->uvc_ss_streaming_cls;
1822 
1823 	return NULL;
1824 }
1825 
1826 enum uvcg_strm_type {
1827 	UVCG_HEADER = 0,
1828 	UVCG_FORMAT,
1829 	UVCG_FRAME
1830 };
1831 
1832 /*
1833  * Iterate over a hierarchy of streaming descriptors' config items.
1834  * The items are created by the user with configfs.
1835  *
1836  * It "processes" the header pointed to by @priv1, then for each format
1837  * that follows the header "processes" the format itself and then for
1838  * each frame inside a format "processes" the frame.
1839  *
1840  * As a "processing" function the @fun is used.
1841  *
1842  * __uvcg_iter_strm_cls() is used in two context: first, to calculate
1843  * the amount of memory needed for an array of streaming descriptors
1844  * and second, to actually fill the array.
1845  *
1846  * @h: streaming header pointer
1847  * @priv2: an "inout" parameter (the caller might want to see the changes to it)
1848  * @priv3: an "inout" parameter (the caller might want to see the changes to it)
1849  * @fun: callback function for processing each level of the hierarchy
1850  */
__uvcg_iter_strm_cls(struct uvcg_streaming_header * h,void * priv2,void * priv3,int (* fun)(void *,void *,void *,int,enum uvcg_strm_type type))1851 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
1852 	void *priv2, void *priv3,
1853 	int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type))
1854 {
1855 	struct uvcg_format_ptr *f;
1856 	struct config_group *grp;
1857 	struct config_item *item;
1858 	struct uvcg_frame *frm;
1859 	int ret, i, j;
1860 
1861 	if (!fun)
1862 		return -EINVAL;
1863 
1864 	i = j = 0;
1865 	ret = fun(h, priv2, priv3, 0, UVCG_HEADER);
1866 	if (ret)
1867 		return ret;
1868 	list_for_each_entry(f, &h->formats, entry) {
1869 		ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT);
1870 		if (ret)
1871 			return ret;
1872 		grp = &f->fmt->group;
1873 		list_for_each_entry(item, &grp->cg_children, ci_entry) {
1874 			frm = to_uvcg_frame(item);
1875 			ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
1876 			if (ret)
1877 				return ret;
1878 		}
1879 	}
1880 
1881 	return ret;
1882 }
1883 
1884 /*
1885  * Count how many bytes are needed for an array of streaming descriptors.
1886  *
1887  * @priv1: pointer to a header, format or frame
1888  * @priv2: inout parameter, accumulated size of the array
1889  * @priv3: inout parameter, accumulated number of the array elements
1890  * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
1891  */
__uvcg_cnt_strm(void * priv1,void * priv2,void * priv3,int n,enum uvcg_strm_type type)1892 static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
1893 			   enum uvcg_strm_type type)
1894 {
1895 	size_t *size = priv2;
1896 	size_t *count = priv3;
1897 
1898 	switch (type) {
1899 	case UVCG_HEADER: {
1900 		struct uvcg_streaming_header *h = priv1;
1901 
1902 		*size += sizeof(h->desc);
1903 		/* bmaControls */
1904 		*size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE;
1905 	}
1906 	break;
1907 	case UVCG_FORMAT: {
1908 		struct uvcg_format *fmt = priv1;
1909 
1910 		if (fmt->type == UVCG_UNCOMPRESSED) {
1911 			struct uvcg_uncompressed *u =
1912 				container_of(fmt, struct uvcg_uncompressed,
1913 					     fmt);
1914 
1915 			*size += sizeof(u->desc);
1916 		} else if (fmt->type == UVCG_MJPEG) {
1917 			struct uvcg_mjpeg *m =
1918 				container_of(fmt, struct uvcg_mjpeg, fmt);
1919 
1920 			*size += sizeof(m->desc);
1921 		} else {
1922 			return -EINVAL;
1923 		}
1924 	}
1925 	break;
1926 	case UVCG_FRAME: {
1927 		struct uvcg_frame *frm = priv1;
1928 		int sz = sizeof(frm->dw_frame_interval);
1929 
1930 		*size += sizeof(frm->frame);
1931 		*size += frm->frame.b_frame_interval_type * sz;
1932 	}
1933 	break;
1934 	}
1935 
1936 	++*count;
1937 
1938 	return 0;
1939 }
1940 
1941 /*
1942  * Fill an array of streaming descriptors.
1943  *
1944  * @priv1: pointer to a header, format or frame
1945  * @priv2: inout parameter, pointer into a block of memory
1946  * @priv3: inout parameter, pointer to a 2-dimensional array
1947  */
__uvcg_fill_strm(void * priv1,void * priv2,void * priv3,int n,enum uvcg_strm_type type)1948 static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
1949 			    enum uvcg_strm_type type)
1950 {
1951 	void **dest = priv2;
1952 	struct uvc_descriptor_header ***array = priv3;
1953 	size_t sz;
1954 
1955 	**array = *dest;
1956 	++*array;
1957 
1958 	switch (type) {
1959 	case UVCG_HEADER: {
1960 		struct uvc_input_header_descriptor *ihdr = *dest;
1961 		struct uvcg_streaming_header *h = priv1;
1962 		struct uvcg_format_ptr *f;
1963 
1964 		memcpy(*dest, &h->desc, sizeof(h->desc));
1965 		*dest += sizeof(h->desc);
1966 		sz = UVCG_STREAMING_CONTROL_SIZE;
1967 		list_for_each_entry(f, &h->formats, entry) {
1968 			memcpy(*dest, f->fmt->bmaControls, sz);
1969 			*dest += sz;
1970 		}
1971 		ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz;
1972 		ihdr->bNumFormats = h->num_fmt;
1973 	}
1974 	break;
1975 	case UVCG_FORMAT: {
1976 		struct uvcg_format *fmt = priv1;
1977 
1978 		if (fmt->type == UVCG_UNCOMPRESSED) {
1979 			struct uvc_format_uncompressed *unc = *dest;
1980 			struct uvcg_uncompressed *u =
1981 				container_of(fmt, struct uvcg_uncompressed,
1982 					     fmt);
1983 
1984 			memcpy(*dest, &u->desc, sizeof(u->desc));
1985 			*dest += sizeof(u->desc);
1986 			unc->bNumFrameDescriptors = fmt->num_frames;
1987 			unc->bFormatIndex = n + 1;
1988 		} else if (fmt->type == UVCG_MJPEG) {
1989 			struct uvc_format_mjpeg *mjp = *dest;
1990 			struct uvcg_mjpeg *m =
1991 				container_of(fmt, struct uvcg_mjpeg, fmt);
1992 
1993 			memcpy(*dest, &m->desc, sizeof(m->desc));
1994 			*dest += sizeof(m->desc);
1995 			mjp->bNumFrameDescriptors = fmt->num_frames;
1996 			mjp->bFormatIndex = n + 1;
1997 		} else {
1998 			return -EINVAL;
1999 		}
2000 	}
2001 	break;
2002 	case UVCG_FRAME: {
2003 		struct uvcg_frame *frm = priv1;
2004 		struct uvc_descriptor_header *h = *dest;
2005 
2006 		sz = sizeof(frm->frame);
2007 		memcpy(*dest, &frm->frame, sz);
2008 		*dest += sz;
2009 		sz = frm->frame.b_frame_interval_type *
2010 			sizeof(*frm->dw_frame_interval);
2011 		memcpy(*dest, frm->dw_frame_interval, sz);
2012 		*dest += sz;
2013 		if (frm->fmt_type == UVCG_UNCOMPRESSED)
2014 			h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
2015 				frm->frame.b_frame_interval_type);
2016 		else if (frm->fmt_type == UVCG_MJPEG)
2017 			h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
2018 				frm->frame.b_frame_interval_type);
2019 	}
2020 	break;
2021 	}
2022 
2023 	return 0;
2024 }
2025 
uvcg_streaming_class_allow_link(struct config_item * src,struct config_item * target)2026 static int uvcg_streaming_class_allow_link(struct config_item *src,
2027 					   struct config_item *target)
2028 {
2029 	struct config_item *streaming, *header;
2030 	struct f_uvc_opts *opts;
2031 	struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2032 	struct uvc_descriptor_header ***class_array, **cl_arr;
2033 	struct uvcg_streaming_header *target_hdr;
2034 	void *data, *data_save;
2035 	size_t size = 0, count = 0;
2036 	int ret = -EINVAL;
2037 
2038 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2039 
2040 	streaming = src->ci_parent->ci_parent;
2041 	header = config_group_find_item(to_config_group(streaming), "header");
2042 	if (!header || target->ci_parent != header)
2043 		goto out;
2044 
2045 	opts = to_f_uvc_opts(streaming->ci_parent);
2046 
2047 	mutex_lock(&opts->lock);
2048 
2049 	class_array = __uvcg_get_stream_class_arr(src, opts);
2050 	if (!class_array || *class_array || opts->refcnt) {
2051 		ret = -EBUSY;
2052 		goto unlock;
2053 	}
2054 
2055 	target_hdr = to_uvcg_streaming_header(target);
2056 	ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm);
2057 	if (ret)
2058 		goto unlock;
2059 
2060 	count += 2; /* color_matching, NULL */
2061 	*class_array = kcalloc(count, sizeof(void *), GFP_KERNEL);
2062 	if (!*class_array) {
2063 		ret = -ENOMEM;
2064 		goto unlock;
2065 	}
2066 
2067 	data = data_save = kzalloc(size, GFP_KERNEL);
2068 	if (!data) {
2069 		kfree(*class_array);
2070 		*class_array = NULL;
2071 		ret = PTR_ERR(data);
2072 		goto unlock;
2073 	}
2074 	cl_arr = *class_array;
2075 	ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr,
2076 				   __uvcg_fill_strm);
2077 	if (ret) {
2078 		kfree(*class_array);
2079 		*class_array = NULL;
2080 		/*
2081 		 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2082 		 * might have advanced the "data", so use a backup copy
2083 		 */
2084 		kfree(data_save);
2085 		goto unlock;
2086 	}
2087 	*cl_arr = (struct uvc_descriptor_header *)&opts->uvc_color_matching;
2088 
2089 	++target_hdr->linked;
2090 	ret = 0;
2091 
2092 unlock:
2093 	mutex_unlock(&opts->lock);
2094 out:
2095 	config_item_put(header);
2096 	mutex_unlock(su_mutex);
2097 	return ret;
2098 }
2099 
uvcg_streaming_class_drop_link(struct config_item * src,struct config_item * target)2100 static int uvcg_streaming_class_drop_link(struct config_item *src,
2101 					  struct config_item *target)
2102 {
2103 	struct config_item *streaming, *header;
2104 	struct f_uvc_opts *opts;
2105 	struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2106 	struct uvc_descriptor_header ***class_array;
2107 	struct uvcg_streaming_header *target_hdr;
2108 	int ret = -EINVAL;
2109 
2110 	mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2111 
2112 	streaming = src->ci_parent->ci_parent;
2113 	header = config_group_find_item(to_config_group(streaming), "header");
2114 	if (!header || target->ci_parent != header)
2115 		goto out;
2116 
2117 	opts = to_f_uvc_opts(streaming->ci_parent);
2118 
2119 	mutex_lock(&opts->lock);
2120 
2121 	class_array = __uvcg_get_stream_class_arr(src, opts);
2122 	if (!class_array || !*class_array)
2123 		goto unlock;
2124 
2125 	if (opts->refcnt) {
2126 		ret = -EBUSY;
2127 		goto unlock;
2128 	}
2129 
2130 	target_hdr = to_uvcg_streaming_header(target);
2131 	--target_hdr->linked;
2132 	kfree(**class_array);
2133 	kfree(*class_array);
2134 	*class_array = NULL;
2135 	ret = 0;
2136 
2137 unlock:
2138 	mutex_unlock(&opts->lock);
2139 out:
2140 	config_item_put(header);
2141 	mutex_unlock(su_mutex);
2142 	return ret;
2143 }
2144 
2145 static struct configfs_item_operations uvcg_streaming_class_item_ops = {
2146 	.allow_link	= uvcg_streaming_class_allow_link,
2147 	.drop_link	= uvcg_streaming_class_drop_link,
2148 };
2149 
2150 static struct config_item_type uvcg_streaming_class_type = {
2151 	.ct_item_ops	= &uvcg_streaming_class_item_ops,
2152 	.ct_owner	= THIS_MODULE,
2153 };
2154 
2155 static struct config_group *uvcg_streaming_class_default_groups[] = {
2156 	&uvcg_streaming_class_fs.group,
2157 	&uvcg_streaming_class_hs.group,
2158 	&uvcg_streaming_class_ss.group,
2159 	NULL,
2160 };
2161 
2162 /* streaming/class */
2163 static struct uvcg_streaming_class_grp {
2164 	struct config_group	group;
2165 } uvcg_streaming_class_grp;
2166 
2167 static struct config_item_type uvcg_streaming_class_grp_type = {
2168 	.ct_owner = THIS_MODULE,
2169 };
2170 
2171 static struct config_group *uvcg_streaming_default_groups[] = {
2172 	&uvcg_streaming_header_grp.group,
2173 	&uvcg_uncompressed_grp.group,
2174 	&uvcg_mjpeg_grp.group,
2175 	&uvcg_color_matching_grp.group,
2176 	&uvcg_streaming_class_grp.group,
2177 	NULL,
2178 };
2179 
2180 /* streaming */
2181 static struct uvcg_streaming_grp {
2182 	struct config_group	group;
2183 } uvcg_streaming_grp;
2184 
2185 static struct config_item_type uvcg_streaming_grp_type = {
2186 	.ct_owner = THIS_MODULE,
2187 };
2188 
2189 static struct config_group *uvcg_default_groups[] = {
2190 	&uvcg_control_grp.group,
2191 	&uvcg_streaming_grp.group,
2192 	NULL,
2193 };
2194 
to_f_uvc_opts(struct config_item * item)2195 static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
2196 {
2197 	return container_of(to_config_group(item), struct f_uvc_opts,
2198 			    func_inst.group);
2199 }
2200 
uvc_attr_release(struct config_item * item)2201 static void uvc_attr_release(struct config_item *item)
2202 {
2203 	struct f_uvc_opts *opts = to_f_uvc_opts(item);
2204 
2205 	usb_put_function_instance(&opts->func_inst);
2206 }
2207 
2208 static struct configfs_item_operations uvc_item_ops = {
2209 	.release		= uvc_attr_release,
2210 };
2211 
2212 #define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit)	\
2213 static ssize_t f_uvc_opts_##cname##_show(				\
2214 	struct config_item *item, char *page)				\
2215 {									\
2216 	struct f_uvc_opts *opts = to_f_uvc_opts(item);			\
2217 	int result;							\
2218 									\
2219 	mutex_lock(&opts->lock);					\
2220 	result = sprintf(page, "%d\n", conv(opts->cname));		\
2221 	mutex_unlock(&opts->lock);					\
2222 									\
2223 	return result;							\
2224 }									\
2225 									\
2226 static ssize_t								\
2227 f_uvc_opts_##cname##_store(struct config_item *item,			\
2228 			   const char *page, size_t len)		\
2229 {									\
2230 	struct f_uvc_opts *opts = to_f_uvc_opts(item);			\
2231 	int ret;							\
2232 	uxx num;							\
2233 									\
2234 	mutex_lock(&opts->lock);					\
2235 	if (opts->refcnt) {						\
2236 		ret = -EBUSY;						\
2237 		goto end;						\
2238 	}								\
2239 									\
2240 	ret = str2u(page, 0, &num);					\
2241 	if (ret)							\
2242 		goto end;						\
2243 									\
2244 	if (num > limit) {						\
2245 		ret = -EINVAL;						\
2246 		goto end;						\
2247 	}								\
2248 	opts->cname = vnoc(num);					\
2249 	ret = len;							\
2250 end:									\
2251 	mutex_unlock(&opts->lock);					\
2252 	return ret;							\
2253 }									\
2254 									\
2255 UVC_ATTR(f_uvc_opts_, cname, cname)
2256 
2257 #define identity_conv(x) (x)
2258 
2259 UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv,
2260 	       kstrtou8, u8, identity_conv, 16);
2261 UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu,
2262 	       kstrtou16, u16, le16_to_cpu, 3072);
2263 UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv,
2264 	       kstrtou8, u8, identity_conv, 15);
2265 
2266 #undef identity_conv
2267 
2268 #undef UVCG_OPTS_ATTR
2269 
2270 static struct configfs_attribute *uvc_attrs[] = {
2271 	&f_uvc_opts_attr_streaming_interval,
2272 	&f_uvc_opts_attr_streaming_maxpacket,
2273 	&f_uvc_opts_attr_streaming_maxburst,
2274 	NULL,
2275 };
2276 
2277 static struct config_item_type uvc_func_type = {
2278 	.ct_item_ops	= &uvc_item_ops,
2279 	.ct_attrs	= uvc_attrs,
2280 	.ct_owner	= THIS_MODULE,
2281 };
2282 
uvcg_init_group(struct config_group * g,struct config_group ** default_groups,const char * name,struct config_item_type * type)2283 static inline void uvcg_init_group(struct config_group *g,
2284 				   struct config_group **default_groups,
2285 				   const char *name,
2286 				   struct config_item_type *type)
2287 {
2288 	g->default_groups = default_groups;
2289 	config_group_init_type_name(g, name, type);
2290 }
2291 
uvcg_attach_configfs(struct f_uvc_opts * opts)2292 int uvcg_attach_configfs(struct f_uvc_opts *opts)
2293 {
2294 	config_group_init_type_name(&uvcg_control_header_grp.group,
2295 				    "header",
2296 				    &uvcg_control_header_grp_type);
2297 	config_group_init_type_name(&uvcg_default_processing.group,
2298 				    "default",
2299 				    &uvcg_default_processing_type);
2300 	uvcg_init_group(&uvcg_processing_grp.group,
2301 			uvcg_processing_default_groups,
2302 			"processing",
2303 			&uvcg_processing_grp_type);
2304 	config_group_init_type_name(&uvcg_default_camera.group,
2305 				    "default",
2306 				    &uvcg_default_camera_type);
2307 	uvcg_init_group(&uvcg_camera_grp.group,
2308 			uvcg_camera_default_groups,
2309 			"camera",
2310 			&uvcg_camera_grp_type);
2311 	config_group_init_type_name(&uvcg_default_output.group,
2312 				    "default",
2313 				    &uvcg_default_output_type);
2314 	uvcg_init_group(&uvcg_output_grp.group,
2315 			uvcg_output_default_groups,
2316 			"output",
2317 			&uvcg_output_grp_type);
2318 	uvcg_init_group(&uvcg_terminal_grp.group,
2319 			uvcg_terminal_default_groups,
2320 			"terminal",
2321 			&uvcg_terminal_grp_type);
2322 	config_group_init_type_name(&uvcg_control_class_fs.group,
2323 				    "fs",
2324 				    &uvcg_control_class_type);
2325 	config_group_init_type_name(&uvcg_control_class_ss.group,
2326 				    "ss",
2327 				    &uvcg_control_class_type);
2328 	uvcg_init_group(&uvcg_control_class_grp.group,
2329 			uvcg_control_class_default_groups,
2330 			"class",
2331 			&uvcg_control_class_grp_type);
2332 	uvcg_init_group(&uvcg_control_grp.group,
2333 			uvcg_control_default_groups,
2334 			"control",
2335 			&uvcg_control_grp_type);
2336 	config_group_init_type_name(&uvcg_streaming_header_grp.group,
2337 				    "header",
2338 				    &uvcg_streaming_header_grp_type);
2339 	config_group_init_type_name(&uvcg_uncompressed_grp.group,
2340 				    "uncompressed",
2341 				    &uvcg_uncompressed_grp_type);
2342 	config_group_init_type_name(&uvcg_mjpeg_grp.group,
2343 				    "mjpeg",
2344 				    &uvcg_mjpeg_grp_type);
2345 	config_group_init_type_name(&uvcg_default_color_matching.group,
2346 				    "default",
2347 				    &uvcg_default_color_matching_type);
2348 	uvcg_init_group(&uvcg_color_matching_grp.group,
2349 			uvcg_color_matching_default_groups,
2350 			"color_matching",
2351 			&uvcg_color_matching_grp_type);
2352 	config_group_init_type_name(&uvcg_streaming_class_fs.group,
2353 				    "fs",
2354 				    &uvcg_streaming_class_type);
2355 	config_group_init_type_name(&uvcg_streaming_class_hs.group,
2356 				    "hs",
2357 				    &uvcg_streaming_class_type);
2358 	config_group_init_type_name(&uvcg_streaming_class_ss.group,
2359 				    "ss",
2360 				    &uvcg_streaming_class_type);
2361 	uvcg_init_group(&uvcg_streaming_class_grp.group,
2362 			uvcg_streaming_class_default_groups,
2363 			"class",
2364 			&uvcg_streaming_class_grp_type);
2365 	uvcg_init_group(&uvcg_streaming_grp.group,
2366 			uvcg_streaming_default_groups,
2367 			"streaming",
2368 			&uvcg_streaming_grp_type);
2369 	uvcg_init_group(&opts->func_inst.group,
2370 			uvcg_default_groups,
2371 			"",
2372 			&uvc_func_type);
2373 	return 0;
2374 }
2375