1 // SPDX-License-Identifier: GPL-2.0
5 * Configfs support for the uvc function.
7 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
8 * http://www.samsung.com
10 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
13 #include <linux/sort.h>
16 #include "uvc_configfs.h"
18 #define UVCG_STREAMING_CONTROL_SIZE 1
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, \
29 #define UVC_ATTR_RO(prefix, cname, aname) \
30 static struct configfs_attribute prefix##attr_##cname = { \
31 .ca_name = __stringify(aname), \
33 .ca_owner = THIS_MODULE, \
34 .show = prefix##cname##_show, \
37 static int uvcg_config_compare_u32(const void *l, const void *r)
39 u32 li = *(const u32 *)l;
40 u32 ri = *(const u32 *)r;
42 return li < ri ? -1 : li == ri ? 0 : 1;
45 static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
47 return container_of(to_config_group(item), struct f_uvc_opts,
51 /* control/header/<NAME> */
52 DECLARE_UVC_HEADER_DESCRIPTOR(1);
54 struct uvcg_control_header {
55 struct config_item item;
56 struct UVC_HEADER_DESCRIPTOR(1) desc;
60 static struct uvcg_control_header *to_uvcg_control_header(struct config_item *item)
62 return container_of(item, struct uvcg_control_header, item);
65 #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
66 static ssize_t uvcg_control_header_##cname##_show( \
67 struct config_item *item, char *page) \
69 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
70 struct f_uvc_opts *opts; \
71 struct config_item *opts_item; \
72 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
75 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
77 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
78 opts = to_f_uvc_opts(opts_item); \
80 mutex_lock(&opts->lock); \
81 result = sprintf(page, "%d\n", conv(ch->desc.aname)); \
82 mutex_unlock(&opts->lock); \
84 mutex_unlock(su_mutex); \
89 uvcg_control_header_##cname##_store(struct config_item *item, \
90 const char *page, size_t len) \
92 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
93 struct f_uvc_opts *opts; \
94 struct config_item *opts_item; \
95 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
99 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
101 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
102 opts = to_f_uvc_opts(opts_item); \
104 mutex_lock(&opts->lock); \
105 if (ch->linked || opts->refcnt) { \
110 ret = str2u(page, 0, &num); \
118 ch->desc.aname = vnoc(num); \
121 mutex_unlock(&opts->lock); \
122 mutex_unlock(su_mutex); \
126 UVC_ATTR(uvcg_control_header_, cname, aname)
128 UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
131 UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32,
132 u32, cpu_to_le32, 0x7fffffff);
134 #undef UVCG_CTRL_HDR_ATTR
136 static struct configfs_attribute *uvcg_control_header_attrs[] = {
137 &uvcg_control_header_attr_bcd_uvc,
138 &uvcg_control_header_attr_dw_clock_frequency,
142 static const struct config_item_type uvcg_control_header_type = {
143 .ct_attrs = uvcg_control_header_attrs,
144 .ct_owner = THIS_MODULE,
147 static struct config_item *uvcg_control_header_make(struct config_group *group,
150 struct uvcg_control_header *h;
152 h = kzalloc(sizeof(*h), GFP_KERNEL);
154 return ERR_PTR(-ENOMEM);
156 h->desc.bLength = UVC_DT_HEADER_SIZE(1);
157 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
158 h->desc.bDescriptorSubType = UVC_VC_HEADER;
159 h->desc.bcdUVC = cpu_to_le16(0x0100);
160 h->desc.dwClockFrequency = cpu_to_le32(48000000);
162 config_item_init_type_name(&h->item, name, &uvcg_control_header_type);
167 static void uvcg_control_header_drop(struct config_group *group,
168 struct config_item *item)
170 struct uvcg_control_header *h = to_uvcg_control_header(item);
176 static struct uvcg_control_header_grp {
177 struct config_group group;
178 } uvcg_control_header_grp;
180 static struct configfs_group_operations uvcg_control_header_grp_ops = {
181 .make_item = uvcg_control_header_make,
182 .drop_item = uvcg_control_header_drop,
185 static const struct config_item_type uvcg_control_header_grp_type = {
186 .ct_group_ops = &uvcg_control_header_grp_ops,
187 .ct_owner = THIS_MODULE,
190 /* control/processing/default */
191 static struct uvcg_default_processing {
192 struct config_group group;
193 } uvcg_default_processing;
195 static inline struct uvcg_default_processing
196 *to_uvcg_default_processing(struct config_item *item)
198 return container_of(to_config_group(item),
199 struct uvcg_default_processing, group);
202 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
203 static ssize_t uvcg_default_processing_##cname##_show( \
204 struct config_item *item, char *page) \
206 struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
207 struct f_uvc_opts *opts; \
208 struct config_item *opts_item; \
209 struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
210 struct uvc_processing_unit_descriptor *pd; \
213 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
215 opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \
216 opts = to_f_uvc_opts(opts_item); \
217 pd = &opts->uvc_processing; \
219 mutex_lock(&opts->lock); \
220 result = sprintf(page, "%d\n", conv(pd->aname)); \
221 mutex_unlock(&opts->lock); \
223 mutex_unlock(su_mutex); \
227 UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
229 #define identity_conv(x) (x)
231 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, identity_conv);
232 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, identity_conv);
233 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, le16_to_cpu);
234 UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv);
238 #undef UVCG_DEFAULT_PROCESSING_ATTR
240 static ssize_t uvcg_default_processing_bm_controls_show(
241 struct config_item *item, char *page)
243 struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
244 struct f_uvc_opts *opts;
245 struct config_item *opts_item;
246 struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
247 struct uvc_processing_unit_descriptor *pd;
251 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
253 opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
254 opts = to_f_uvc_opts(opts_item);
255 pd = &opts->uvc_processing;
257 mutex_lock(&opts->lock);
258 for (result = 0, i = 0; i < pd->bControlSize; ++i) {
259 result += sprintf(pg, "%d\n", pd->bmControls[i]);
262 mutex_unlock(&opts->lock);
264 mutex_unlock(su_mutex);
269 UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
271 static struct configfs_attribute *uvcg_default_processing_attrs[] = {
272 &uvcg_default_processing_attr_b_unit_id,
273 &uvcg_default_processing_attr_b_source_id,
274 &uvcg_default_processing_attr_w_max_multiplier,
275 &uvcg_default_processing_attr_bm_controls,
276 &uvcg_default_processing_attr_i_processing,
280 static const struct config_item_type uvcg_default_processing_type = {
281 .ct_attrs = uvcg_default_processing_attrs,
282 .ct_owner = THIS_MODULE,
285 /* struct uvcg_processing {}; */
287 /* control/processing */
288 static struct uvcg_processing_grp {
289 struct config_group group;
290 } uvcg_processing_grp;
292 static const struct config_item_type uvcg_processing_grp_type = {
293 .ct_owner = THIS_MODULE,
296 /* control/terminal/camera/default */
297 static struct uvcg_default_camera {
298 struct config_group group;
299 } uvcg_default_camera;
301 static inline struct uvcg_default_camera
302 *to_uvcg_default_camera(struct config_item *item)
304 return container_of(to_config_group(item),
305 struct uvcg_default_camera, group);
308 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
309 static ssize_t uvcg_default_camera_##cname##_show( \
310 struct config_item *item, char *page) \
312 struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \
313 struct f_uvc_opts *opts; \
314 struct config_item *opts_item; \
315 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
316 struct uvc_camera_terminal_descriptor *cd; \
319 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
321 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> \
323 opts = to_f_uvc_opts(opts_item); \
324 cd = &opts->uvc_camera_terminal; \
326 mutex_lock(&opts->lock); \
327 result = sprintf(page, "%d\n", conv(cd->aname)); \
328 mutex_unlock(&opts->lock); \
330 mutex_unlock(su_mutex); \
335 UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
337 #define identity_conv(x) (x)
339 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, identity_conv);
340 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, le16_to_cpu);
341 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv);
342 UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, identity_conv);
343 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
345 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
347 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
352 #undef UVCG_DEFAULT_CAMERA_ATTR
354 static ssize_t uvcg_default_camera_bm_controls_show(
355 struct config_item *item, char *page)
357 struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
358 struct f_uvc_opts *opts;
359 struct config_item *opts_item;
360 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
361 struct uvc_camera_terminal_descriptor *cd;
365 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
367 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent->
369 opts = to_f_uvc_opts(opts_item);
370 cd = &opts->uvc_camera_terminal;
372 mutex_lock(&opts->lock);
373 for (result = 0, i = 0; i < cd->bControlSize; ++i) {
374 result += sprintf(pg, "%d\n", cd->bmControls[i]);
377 mutex_unlock(&opts->lock);
379 mutex_unlock(su_mutex);
383 UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
385 static struct configfs_attribute *uvcg_default_camera_attrs[] = {
386 &uvcg_default_camera_attr_b_terminal_id,
387 &uvcg_default_camera_attr_w_terminal_type,
388 &uvcg_default_camera_attr_b_assoc_terminal,
389 &uvcg_default_camera_attr_i_terminal,
390 &uvcg_default_camera_attr_w_objective_focal_length_min,
391 &uvcg_default_camera_attr_w_objective_focal_length_max,
392 &uvcg_default_camera_attr_w_ocular_focal_length,
393 &uvcg_default_camera_attr_bm_controls,
397 static const struct config_item_type uvcg_default_camera_type = {
398 .ct_attrs = uvcg_default_camera_attrs,
399 .ct_owner = THIS_MODULE,
402 /* struct uvcg_camera {}; */
404 /* control/terminal/camera */
405 static struct uvcg_camera_grp {
406 struct config_group group;
409 static const struct config_item_type uvcg_camera_grp_type = {
410 .ct_owner = THIS_MODULE,
413 /* control/terminal/output/default */
414 static struct uvcg_default_output {
415 struct config_group group;
416 } uvcg_default_output;
418 static inline struct uvcg_default_output
419 *to_uvcg_default_output(struct config_item *item)
421 return container_of(to_config_group(item),
422 struct uvcg_default_output, group);
425 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
426 static ssize_t uvcg_default_output_##cname##_show( \
427 struct config_item *item, char *page) \
429 struct uvcg_default_output *dout = to_uvcg_default_output(item); \
430 struct f_uvc_opts *opts; \
431 struct config_item *opts_item; \
432 struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
433 struct uvc_output_terminal_descriptor *cd; \
436 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
438 opts_item = dout->group.cg_item.ci_parent->ci_parent-> \
439 ci_parent->ci_parent; \
440 opts = to_f_uvc_opts(opts_item); \
441 cd = &opts->uvc_output_terminal; \
443 mutex_lock(&opts->lock); \
444 result = sprintf(page, "%d\n", conv(cd->aname)); \
445 mutex_unlock(&opts->lock); \
447 mutex_unlock(su_mutex); \
452 UVC_ATTR_RO(uvcg_default_output_, cname, aname)
454 #define identity_conv(x) (x)
456 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, identity_conv);
457 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, le16_to_cpu);
458 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv);
459 UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, identity_conv);
460 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv);
464 #undef UVCG_DEFAULT_OUTPUT_ATTR
466 static struct configfs_attribute *uvcg_default_output_attrs[] = {
467 &uvcg_default_output_attr_b_terminal_id,
468 &uvcg_default_output_attr_w_terminal_type,
469 &uvcg_default_output_attr_b_assoc_terminal,
470 &uvcg_default_output_attr_b_source_id,
471 &uvcg_default_output_attr_i_terminal,
475 static const struct config_item_type uvcg_default_output_type = {
476 .ct_attrs = uvcg_default_output_attrs,
477 .ct_owner = THIS_MODULE,
480 /* struct uvcg_output {}; */
482 /* control/terminal/output */
483 static struct uvcg_output_grp {
484 struct config_group group;
487 static const struct config_item_type uvcg_output_grp_type = {
488 .ct_owner = THIS_MODULE,
491 /* control/terminal */
492 static struct uvcg_terminal_grp {
493 struct config_group group;
496 static const struct config_item_type uvcg_terminal_grp_type = {
497 .ct_owner = THIS_MODULE,
500 /* control/class/{fs} */
501 static struct uvcg_control_class {
502 struct config_group group;
503 } uvcg_control_class_fs, uvcg_control_class_ss;
506 static inline struct uvc_descriptor_header
507 **uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
509 struct uvcg_control_class *cl = container_of(to_config_group(i),
510 struct uvcg_control_class, group);
512 if (cl == &uvcg_control_class_fs)
513 return o->uvc_fs_control_cls;
515 if (cl == &uvcg_control_class_ss)
516 return o->uvc_ss_control_cls;
521 static int uvcg_control_class_allow_link(struct config_item *src,
522 struct config_item *target)
524 struct config_item *control, *header;
525 struct f_uvc_opts *opts;
526 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
527 struct uvc_descriptor_header **class_array;
528 struct uvcg_control_header *target_hdr;
531 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
533 control = src->ci_parent->ci_parent;
534 header = config_group_find_item(to_config_group(control), "header");
535 if (!header || target->ci_parent != header)
538 opts = to_f_uvc_opts(control->ci_parent);
540 mutex_lock(&opts->lock);
542 class_array = uvcg_get_ctl_class_arr(src, opts);
545 if (opts->refcnt || class_array[0]) {
550 target_hdr = to_uvcg_control_header(target);
551 ++target_hdr->linked;
552 class_array[0] = (struct uvc_descriptor_header *)&target_hdr->desc;
556 mutex_unlock(&opts->lock);
558 config_item_put(header);
559 mutex_unlock(su_mutex);
563 static void uvcg_control_class_drop_link(struct config_item *src,
564 struct config_item *target)
566 struct config_item *control, *header;
567 struct f_uvc_opts *opts;
568 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
569 struct uvc_descriptor_header **class_array;
570 struct uvcg_control_header *target_hdr;
572 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
574 control = src->ci_parent->ci_parent;
575 header = config_group_find_item(to_config_group(control), "header");
576 if (!header || target->ci_parent != header)
579 opts = to_f_uvc_opts(control->ci_parent);
581 mutex_lock(&opts->lock);
583 class_array = uvcg_get_ctl_class_arr(src, opts);
584 if (!class_array || opts->refcnt)
587 target_hdr = to_uvcg_control_header(target);
588 --target_hdr->linked;
589 class_array[0] = NULL;
592 mutex_unlock(&opts->lock);
594 config_item_put(header);
595 mutex_unlock(su_mutex);
598 static struct configfs_item_operations uvcg_control_class_item_ops = {
599 .allow_link = uvcg_control_class_allow_link,
600 .drop_link = uvcg_control_class_drop_link,
603 static const struct config_item_type uvcg_control_class_type = {
604 .ct_item_ops = &uvcg_control_class_item_ops,
605 .ct_owner = THIS_MODULE,
609 static struct uvcg_control_class_grp {
610 struct config_group group;
611 } uvcg_control_class_grp;
613 static const struct config_item_type uvcg_control_class_grp_type = {
614 .ct_owner = THIS_MODULE,
618 static struct uvcg_control_grp {
619 struct config_group group;
622 static const struct config_item_type uvcg_control_grp_type = {
623 .ct_owner = THIS_MODULE,
626 /* streaming/uncompressed */
627 static struct uvcg_uncompressed_grp {
628 struct config_group group;
629 } uvcg_uncompressed_grp;
631 /* streaming/mjpeg */
632 static struct uvcg_mjpeg_grp {
633 struct config_group group;
636 static struct config_item *fmt_parent[] = {
637 &uvcg_uncompressed_grp.group.cg_item,
638 &uvcg_mjpeg_grp.group.cg_item,
641 enum uvcg_format_type {
642 UVCG_UNCOMPRESSED = 0,
647 struct config_group group;
648 enum uvcg_format_type type;
651 __u8 bmaControls[UVCG_STREAMING_CONTROL_SIZE];
654 static struct uvcg_format *to_uvcg_format(struct config_item *item)
656 return container_of(to_config_group(item), struct uvcg_format, group);
659 static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
661 struct f_uvc_opts *opts;
662 struct config_item *opts_item;
663 struct mutex *su_mutex = &f->group.cg_subsys->su_mutex;
667 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
669 opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
670 opts = to_f_uvc_opts(opts_item);
672 mutex_lock(&opts->lock);
673 result = sprintf(pg, "0x");
675 for (i = 0; i < UVCG_STREAMING_CONTROL_SIZE; ++i) {
676 result += sprintf(pg, "%x\n", f->bmaControls[i]);
679 mutex_unlock(&opts->lock);
681 mutex_unlock(su_mutex);
685 static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
686 const char *page, size_t len)
688 struct f_uvc_opts *opts;
689 struct config_item *opts_item;
690 struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex;
693 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
695 opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent;
696 opts = to_f_uvc_opts(opts_item);
698 mutex_lock(&opts->lock);
699 if (ch->linked || opts->refcnt) {
704 if (len < 4 || *page != '0' ||
705 (*(page + 1) != 'x' && *(page + 1) != 'X'))
707 ret = hex2bin(ch->bmaControls, page + 2, 1);
712 mutex_unlock(&opts->lock);
713 mutex_unlock(su_mutex);
717 struct uvcg_format_ptr {
718 struct uvcg_format *fmt;
719 struct list_head entry;
722 /* streaming/header/<NAME> */
723 struct uvcg_streaming_header {
724 struct config_item item;
725 struct uvc_input_header_descriptor desc;
727 struct list_head formats;
731 static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item *item)
733 return container_of(item, struct uvcg_streaming_header, item);
736 static int uvcg_streaming_header_allow_link(struct config_item *src,
737 struct config_item *target)
739 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
740 struct config_item *opts_item;
741 struct f_uvc_opts *opts;
742 struct uvcg_streaming_header *src_hdr;
743 struct uvcg_format *target_fmt = NULL;
744 struct uvcg_format_ptr *format_ptr;
745 int i, ret = -EINVAL;
747 src_hdr = to_uvcg_streaming_header(src);
748 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
750 opts_item = src->ci_parent->ci_parent->ci_parent;
751 opts = to_f_uvc_opts(opts_item);
753 mutex_lock(&opts->lock);
755 if (src_hdr->linked) {
760 for (i = 0; i < ARRAY_SIZE(fmt_parent); ++i)
761 if (target->ci_parent == fmt_parent[i])
763 if (i == ARRAY_SIZE(fmt_parent))
766 target_fmt = container_of(to_config_group(target), struct uvcg_format,
771 format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
777 format_ptr->fmt = target_fmt;
778 list_add_tail(&format_ptr->entry, &src_hdr->formats);
780 ++target_fmt->linked;
783 mutex_unlock(&opts->lock);
784 mutex_unlock(su_mutex);
788 static void uvcg_streaming_header_drop_link(struct config_item *src,
789 struct config_item *target)
791 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
792 struct config_item *opts_item;
793 struct f_uvc_opts *opts;
794 struct uvcg_streaming_header *src_hdr;
795 struct uvcg_format *target_fmt = NULL;
796 struct uvcg_format_ptr *format_ptr, *tmp;
798 src_hdr = to_uvcg_streaming_header(src);
799 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
801 opts_item = src->ci_parent->ci_parent->ci_parent;
802 opts = to_f_uvc_opts(opts_item);
804 mutex_lock(&opts->lock);
805 target_fmt = container_of(to_config_group(target), struct uvcg_format,
810 list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
811 if (format_ptr->fmt == target_fmt) {
812 list_del(&format_ptr->entry);
818 --target_fmt->linked;
821 mutex_unlock(&opts->lock);
822 mutex_unlock(su_mutex);
825 static struct configfs_item_operations uvcg_streaming_header_item_ops = {
826 .allow_link = uvcg_streaming_header_allow_link,
827 .drop_link = uvcg_streaming_header_drop_link,
830 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
831 static ssize_t uvcg_streaming_header_##cname##_show( \
832 struct config_item *item, char *page) \
834 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
835 struct f_uvc_opts *opts; \
836 struct config_item *opts_item; \
837 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
840 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
842 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
843 opts = to_f_uvc_opts(opts_item); \
845 mutex_lock(&opts->lock); \
846 result = sprintf(page, "%d\n", conv(sh->desc.aname)); \
847 mutex_unlock(&opts->lock); \
849 mutex_unlock(su_mutex); \
853 UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
855 #define identity_conv(x) (x)
857 UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, identity_conv);
858 UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, identity_conv);
859 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod,
861 UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, identity_conv);
862 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv);
866 #undef UVCG_STREAMING_HEADER_ATTR
868 static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
869 &uvcg_streaming_header_attr_bm_info,
870 &uvcg_streaming_header_attr_b_terminal_link,
871 &uvcg_streaming_header_attr_b_still_capture_method,
872 &uvcg_streaming_header_attr_b_trigger_support,
873 &uvcg_streaming_header_attr_b_trigger_usage,
877 static const struct config_item_type uvcg_streaming_header_type = {
878 .ct_item_ops = &uvcg_streaming_header_item_ops,
879 .ct_attrs = uvcg_streaming_header_attrs,
880 .ct_owner = THIS_MODULE,
883 static struct config_item
884 *uvcg_streaming_header_make(struct config_group *group, const char *name)
886 struct uvcg_streaming_header *h;
888 h = kzalloc(sizeof(*h), GFP_KERNEL);
890 return ERR_PTR(-ENOMEM);
892 INIT_LIST_HEAD(&h->formats);
893 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
894 h->desc.bDescriptorSubType = UVC_VS_INPUT_HEADER;
895 h->desc.bTerminalLink = 3;
896 h->desc.bControlSize = UVCG_STREAMING_CONTROL_SIZE;
898 config_item_init_type_name(&h->item, name, &uvcg_streaming_header_type);
903 static void uvcg_streaming_header_drop(struct config_group *group,
904 struct config_item *item)
906 struct uvcg_streaming_header *h = to_uvcg_streaming_header(item);
911 /* streaming/header */
912 static struct uvcg_streaming_header_grp {
913 struct config_group group;
914 } uvcg_streaming_header_grp;
916 static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
917 .make_item = uvcg_streaming_header_make,
918 .drop_item = uvcg_streaming_header_drop,
921 static const struct config_item_type uvcg_streaming_header_grp_type = {
922 .ct_group_ops = &uvcg_streaming_header_grp_ops,
923 .ct_owner = THIS_MODULE,
926 /* streaming/<mode>/<format>/<NAME> */
930 u8 b_descriptor_type;
931 u8 b_descriptor_subtype;
938 u32 dw_max_video_frame_buffer_size;
939 u32 dw_default_frame_interval;
940 u8 b_frame_interval_type;
941 } __attribute__((packed)) frame;
942 u32 *dw_frame_interval;
943 enum uvcg_format_type fmt_type;
944 struct config_item item;
947 static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
949 return container_of(item, struct uvcg_frame, item);
952 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
953 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
955 struct uvcg_frame *f = to_uvcg_frame(item); \
956 struct f_uvc_opts *opts; \
957 struct config_item *opts_item; \
958 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
961 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
963 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
964 opts = to_f_uvc_opts(opts_item); \
966 mutex_lock(&opts->lock); \
967 result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \
968 mutex_unlock(&opts->lock); \
970 mutex_unlock(su_mutex); \
974 static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
975 const char *page, size_t len)\
977 struct uvcg_frame *f = to_uvcg_frame(item); \
978 struct f_uvc_opts *opts; \
979 struct config_item *opts_item; \
980 struct uvcg_format *fmt; \
981 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
985 ret = kstrtou##bits(page, 0, &num); \
989 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
991 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
992 opts = to_f_uvc_opts(opts_item); \
993 fmt = to_uvcg_format(f->item.ci_parent); \
995 mutex_lock(&opts->lock); \
996 if (fmt->linked || opts->refcnt) { \
1001 f->frame.cname = to_little_endian(num); \
1004 mutex_unlock(&opts->lock); \
1005 mutex_unlock(su_mutex); \
1009 UVC_ATTR(uvcg_frame_, cname, aname);
1011 #define noop_conversion(x) (x)
1013 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
1014 noop_conversion, 8);
1015 UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
1016 UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
1017 UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32);
1018 UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32);
1019 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize,
1020 le32_to_cpu, cpu_to_le32, 32);
1021 UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
1022 le32_to_cpu, cpu_to_le32, 32);
1024 #undef noop_conversion
1026 #undef UVCG_FRAME_ATTR
1028 static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
1031 struct uvcg_frame *frm = to_uvcg_frame(item);
1032 struct f_uvc_opts *opts;
1033 struct config_item *opts_item;
1034 struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
1038 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1040 opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
1041 opts = to_f_uvc_opts(opts_item);
1043 mutex_lock(&opts->lock);
1044 for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
1045 result += sprintf(pg, "%d\n",
1046 le32_to_cpu(frm->dw_frame_interval[i]));
1049 mutex_unlock(&opts->lock);
1051 mutex_unlock(su_mutex);
1055 static inline int __uvcg_count_frm_intrv(char *buf, void *priv)
1061 static inline int __uvcg_fill_frm_intrv(char *buf, void *priv)
1066 ret = kstrtou32(buf, 0, &num);
1071 **interv = cpu_to_le32(num);
1077 static int __uvcg_iter_frm_intrv(const char *page, size_t len,
1078 int (*fun)(char *, void *), void *priv)
1080 /* sign, base 2 representation, newline, terminator */
1081 char buf[1 + sizeof(u32) * 8 + 1 + 1];
1082 const char *pg = page;
1088 while (pg - page < len) {
1090 while (i < sizeof(buf) && (pg - page < len) &&
1091 *pg != '\0' && *pg != '\n')
1093 if (i == sizeof(buf))
1095 while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
1098 ret = fun(buf, priv);
1106 static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
1107 const char *page, size_t len)
1109 struct uvcg_frame *ch = to_uvcg_frame(item);
1110 struct f_uvc_opts *opts;
1111 struct config_item *opts_item;
1112 struct uvcg_format *fmt;
1113 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
1115 u32 *frm_intrv, *tmp;
1117 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1119 opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
1120 opts = to_f_uvc_opts(opts_item);
1121 fmt = to_uvcg_format(ch->item.ci_parent);
1123 mutex_lock(&opts->lock);
1124 if (fmt->linked || opts->refcnt) {
1129 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n);
1133 tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL);
1139 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp);
1145 kfree(ch->dw_frame_interval);
1146 ch->dw_frame_interval = frm_intrv;
1147 ch->frame.b_frame_interval_type = n;
1148 sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
1149 uvcg_config_compare_u32, NULL);
1153 mutex_unlock(&opts->lock);
1154 mutex_unlock(su_mutex);
1158 UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
1160 static struct configfs_attribute *uvcg_frame_attrs[] = {
1161 &uvcg_frame_attr_bm_capabilities,
1162 &uvcg_frame_attr_w_width,
1163 &uvcg_frame_attr_w_height,
1164 &uvcg_frame_attr_dw_min_bit_rate,
1165 &uvcg_frame_attr_dw_max_bit_rate,
1166 &uvcg_frame_attr_dw_max_video_frame_buffer_size,
1167 &uvcg_frame_attr_dw_default_frame_interval,
1168 &uvcg_frame_attr_dw_frame_interval,
1172 static const struct config_item_type uvcg_frame_type = {
1173 .ct_attrs = uvcg_frame_attrs,
1174 .ct_owner = THIS_MODULE,
1177 static struct config_item *uvcg_frame_make(struct config_group *group,
1180 struct uvcg_frame *h;
1181 struct uvcg_format *fmt;
1182 struct f_uvc_opts *opts;
1183 struct config_item *opts_item;
1185 h = kzalloc(sizeof(*h), GFP_KERNEL);
1187 return ERR_PTR(-ENOMEM);
1189 h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
1190 h->frame.b_frame_index = 1;
1191 h->frame.w_width = cpu_to_le16(640);
1192 h->frame.w_height = cpu_to_le16(360);
1193 h->frame.dw_min_bit_rate = cpu_to_le32(18432000);
1194 h->frame.dw_max_bit_rate = cpu_to_le32(55296000);
1195 h->frame.dw_max_video_frame_buffer_size = cpu_to_le32(460800);
1196 h->frame.dw_default_frame_interval = cpu_to_le32(666666);
1198 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1199 opts = to_f_uvc_opts(opts_item);
1201 mutex_lock(&opts->lock);
1202 fmt = to_uvcg_format(&group->cg_item);
1203 if (fmt->type == UVCG_UNCOMPRESSED) {
1204 h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED;
1205 h->fmt_type = UVCG_UNCOMPRESSED;
1206 } else if (fmt->type == UVCG_MJPEG) {
1207 h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
1208 h->fmt_type = UVCG_MJPEG;
1210 mutex_unlock(&opts->lock);
1212 return ERR_PTR(-EINVAL);
1215 mutex_unlock(&opts->lock);
1217 config_item_init_type_name(&h->item, name, &uvcg_frame_type);
1222 static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
1224 struct uvcg_frame *h = to_uvcg_frame(item);
1225 struct uvcg_format *fmt;
1226 struct f_uvc_opts *opts;
1227 struct config_item *opts_item;
1229 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1230 opts = to_f_uvc_opts(opts_item);
1232 mutex_lock(&opts->lock);
1233 fmt = to_uvcg_format(&group->cg_item);
1236 mutex_unlock(&opts->lock);
1239 /* streaming/uncompressed/<NAME> */
1240 struct uvcg_uncompressed {
1241 struct uvcg_format fmt;
1242 struct uvc_format_uncompressed desc;
1245 static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item)
1247 return container_of(
1248 container_of(to_config_group(item), struct uvcg_format, group),
1249 struct uvcg_uncompressed, fmt);
1252 static struct configfs_group_operations uvcg_uncompressed_group_ops = {
1253 .make_item = uvcg_frame_make,
1254 .drop_item = uvcg_frame_drop,
1257 static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
1260 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1261 struct f_uvc_opts *opts;
1262 struct config_item *opts_item;
1263 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1265 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1267 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1268 opts = to_f_uvc_opts(opts_item);
1270 mutex_lock(&opts->lock);
1271 memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
1272 mutex_unlock(&opts->lock);
1274 mutex_unlock(su_mutex);
1276 return sizeof(ch->desc.guidFormat);
1279 static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
1280 const char *page, size_t len)
1282 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1283 struct f_uvc_opts *opts;
1284 struct config_item *opts_item;
1285 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1288 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1290 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1291 opts = to_f_uvc_opts(opts_item);
1293 mutex_lock(&opts->lock);
1294 if (ch->fmt.linked || opts->refcnt) {
1299 memcpy(ch->desc.guidFormat, page,
1300 min(sizeof(ch->desc.guidFormat), len));
1301 ret = sizeof(ch->desc.guidFormat);
1304 mutex_unlock(&opts->lock);
1305 mutex_unlock(su_mutex);
1309 UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
1311 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
1312 static ssize_t uvcg_uncompressed_##cname##_show( \
1313 struct config_item *item, char *page) \
1315 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1316 struct f_uvc_opts *opts; \
1317 struct config_item *opts_item; \
1318 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1321 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1323 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1324 opts = to_f_uvc_opts(opts_item); \
1326 mutex_lock(&opts->lock); \
1327 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1328 mutex_unlock(&opts->lock); \
1330 mutex_unlock(su_mutex); \
1334 UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
1336 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
1337 static ssize_t uvcg_uncompressed_##cname##_show( \
1338 struct config_item *item, char *page) \
1340 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1341 struct f_uvc_opts *opts; \
1342 struct config_item *opts_item; \
1343 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1346 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1348 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1349 opts = to_f_uvc_opts(opts_item); \
1351 mutex_lock(&opts->lock); \
1352 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1353 mutex_unlock(&opts->lock); \
1355 mutex_unlock(su_mutex); \
1360 uvcg_uncompressed_##cname##_store(struct config_item *item, \
1361 const char *page, size_t len) \
1363 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1364 struct f_uvc_opts *opts; \
1365 struct config_item *opts_item; \
1366 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1370 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1372 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1373 opts = to_f_uvc_opts(opts_item); \
1375 mutex_lock(&opts->lock); \
1376 if (u->fmt.linked || opts->refcnt) { \
1381 ret = kstrtou8(page, 0, &num); \
1389 u->desc.aname = num; \
1392 mutex_unlock(&opts->lock); \
1393 mutex_unlock(su_mutex); \
1397 UVC_ATTR(uvcg_uncompressed_, cname, aname);
1399 #define identity_conv(x) (x)
1401 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv);
1402 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex,
1404 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
1405 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
1406 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
1408 #undef identity_conv
1410 #undef UVCG_UNCOMPRESSED_ATTR
1411 #undef UVCG_UNCOMPRESSED_ATTR_RO
1413 static inline ssize_t
1414 uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
1416 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1417 return uvcg_format_bma_controls_show(&unc->fmt, page);
1420 static inline ssize_t
1421 uvcg_uncompressed_bma_controls_store(struct config_item *item,
1422 const char *page, size_t len)
1424 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1425 return uvcg_format_bma_controls_store(&unc->fmt, page, len);
1428 UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
1430 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
1431 &uvcg_uncompressed_attr_guid_format,
1432 &uvcg_uncompressed_attr_b_bits_per_pixel,
1433 &uvcg_uncompressed_attr_b_default_frame_index,
1434 &uvcg_uncompressed_attr_b_aspect_ratio_x,
1435 &uvcg_uncompressed_attr_b_aspect_ratio_y,
1436 &uvcg_uncompressed_attr_bm_interface_flags,
1437 &uvcg_uncompressed_attr_bma_controls,
1441 static const struct config_item_type uvcg_uncompressed_type = {
1442 .ct_group_ops = &uvcg_uncompressed_group_ops,
1443 .ct_attrs = uvcg_uncompressed_attrs,
1444 .ct_owner = THIS_MODULE,
1447 static struct config_group *uvcg_uncompressed_make(struct config_group *group,
1450 static char guid[] = {
1451 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
1452 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1454 struct uvcg_uncompressed *h;
1456 h = kzalloc(sizeof(*h), GFP_KERNEL);
1458 return ERR_PTR(-ENOMEM);
1460 h->desc.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE;
1461 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1462 h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED;
1463 memcpy(h->desc.guidFormat, guid, sizeof(guid));
1464 h->desc.bBitsPerPixel = 16;
1465 h->desc.bDefaultFrameIndex = 1;
1466 h->desc.bAspectRatioX = 0;
1467 h->desc.bAspectRatioY = 0;
1468 h->desc.bmInterfaceFlags = 0;
1469 h->desc.bCopyProtect = 0;
1471 h->fmt.type = UVCG_UNCOMPRESSED;
1472 config_group_init_type_name(&h->fmt.group, name,
1473 &uvcg_uncompressed_type);
1475 return &h->fmt.group;
1478 static void uvcg_uncompressed_drop(struct config_group *group,
1479 struct config_item *item)
1481 struct uvcg_uncompressed *h = to_uvcg_uncompressed(item);
1486 static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
1487 .make_group = uvcg_uncompressed_make,
1488 .drop_item = uvcg_uncompressed_drop,
1491 static const struct config_item_type uvcg_uncompressed_grp_type = {
1492 .ct_group_ops = &uvcg_uncompressed_grp_ops,
1493 .ct_owner = THIS_MODULE,
1496 /* streaming/mjpeg/<NAME> */
1498 struct uvcg_format fmt;
1499 struct uvc_format_mjpeg desc;
1502 static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
1504 return container_of(
1505 container_of(to_config_group(item), struct uvcg_format, group),
1506 struct uvcg_mjpeg, fmt);
1509 static struct configfs_group_operations uvcg_mjpeg_group_ops = {
1510 .make_item = uvcg_frame_make,
1511 .drop_item = uvcg_frame_drop,
1514 #define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
1515 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1517 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1518 struct f_uvc_opts *opts; \
1519 struct config_item *opts_item; \
1520 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1523 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1525 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1526 opts = to_f_uvc_opts(opts_item); \
1528 mutex_lock(&opts->lock); \
1529 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1530 mutex_unlock(&opts->lock); \
1532 mutex_unlock(su_mutex); \
1536 UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
1538 #define UVCG_MJPEG_ATTR(cname, aname, conv) \
1539 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1541 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1542 struct f_uvc_opts *opts; \
1543 struct config_item *opts_item; \
1544 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1547 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1549 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1550 opts = to_f_uvc_opts(opts_item); \
1552 mutex_lock(&opts->lock); \
1553 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1554 mutex_unlock(&opts->lock); \
1556 mutex_unlock(su_mutex); \
1561 uvcg_mjpeg_##cname##_store(struct config_item *item, \
1562 const char *page, size_t len) \
1564 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1565 struct f_uvc_opts *opts; \
1566 struct config_item *opts_item; \
1567 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1571 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1573 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1574 opts = to_f_uvc_opts(opts_item); \
1576 mutex_lock(&opts->lock); \
1577 if (u->fmt.linked || opts->refcnt) { \
1582 ret = kstrtou8(page, 0, &num); \
1590 u->desc.aname = num; \
1593 mutex_unlock(&opts->lock); \
1594 mutex_unlock(su_mutex); \
1598 UVC_ATTR(uvcg_mjpeg_, cname, aname)
1600 #define identity_conv(x) (x)
1602 UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex,
1604 UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv);
1605 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
1606 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
1607 UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
1609 #undef identity_conv
1611 #undef UVCG_MJPEG_ATTR
1612 #undef UVCG_MJPEG_ATTR_RO
1614 static inline ssize_t
1615 uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
1617 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1618 return uvcg_format_bma_controls_show(&u->fmt, page);
1621 static inline ssize_t
1622 uvcg_mjpeg_bma_controls_store(struct config_item *item,
1623 const char *page, size_t len)
1625 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1626 return uvcg_format_bma_controls_store(&u->fmt, page, len);
1629 UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
1631 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
1632 &uvcg_mjpeg_attr_b_default_frame_index,
1633 &uvcg_mjpeg_attr_bm_flags,
1634 &uvcg_mjpeg_attr_b_aspect_ratio_x,
1635 &uvcg_mjpeg_attr_b_aspect_ratio_y,
1636 &uvcg_mjpeg_attr_bm_interface_flags,
1637 &uvcg_mjpeg_attr_bma_controls,
1641 static const struct config_item_type uvcg_mjpeg_type = {
1642 .ct_group_ops = &uvcg_mjpeg_group_ops,
1643 .ct_attrs = uvcg_mjpeg_attrs,
1644 .ct_owner = THIS_MODULE,
1647 static struct config_group *uvcg_mjpeg_make(struct config_group *group,
1650 struct uvcg_mjpeg *h;
1652 h = kzalloc(sizeof(*h), GFP_KERNEL);
1654 return ERR_PTR(-ENOMEM);
1656 h->desc.bLength = UVC_DT_FORMAT_MJPEG_SIZE;
1657 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1658 h->desc.bDescriptorSubType = UVC_VS_FORMAT_MJPEG;
1659 h->desc.bDefaultFrameIndex = 1;
1660 h->desc.bAspectRatioX = 0;
1661 h->desc.bAspectRatioY = 0;
1662 h->desc.bmInterfaceFlags = 0;
1663 h->desc.bCopyProtect = 0;
1665 h->fmt.type = UVCG_MJPEG;
1666 config_group_init_type_name(&h->fmt.group, name,
1669 return &h->fmt.group;
1672 static void uvcg_mjpeg_drop(struct config_group *group,
1673 struct config_item *item)
1675 struct uvcg_mjpeg *h = to_uvcg_mjpeg(item);
1680 static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
1681 .make_group = uvcg_mjpeg_make,
1682 .drop_item = uvcg_mjpeg_drop,
1685 static const struct config_item_type uvcg_mjpeg_grp_type = {
1686 .ct_group_ops = &uvcg_mjpeg_grp_ops,
1687 .ct_owner = THIS_MODULE,
1690 /* streaming/color_matching/default */
1691 static struct uvcg_default_color_matching {
1692 struct config_group group;
1693 } uvcg_default_color_matching;
1695 static inline struct uvcg_default_color_matching
1696 *to_uvcg_default_color_matching(struct config_item *item)
1698 return container_of(to_config_group(item),
1699 struct uvcg_default_color_matching, group);
1702 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
1703 static ssize_t uvcg_default_color_matching_##cname##_show( \
1704 struct config_item *item, char *page) \
1706 struct uvcg_default_color_matching *dc = \
1707 to_uvcg_default_color_matching(item); \
1708 struct f_uvc_opts *opts; \
1709 struct config_item *opts_item; \
1710 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
1711 struct uvc_color_matching_descriptor *cd; \
1714 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1716 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \
1717 opts = to_f_uvc_opts(opts_item); \
1718 cd = &opts->uvc_color_matching; \
1720 mutex_lock(&opts->lock); \
1721 result = sprintf(page, "%d\n", conv(cd->aname)); \
1722 mutex_unlock(&opts->lock); \
1724 mutex_unlock(su_mutex); \
1728 UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
1730 #define identity_conv(x) (x)
1732 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries,
1734 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics,
1735 bTransferCharacteristics, identity_conv);
1736 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients,
1739 #undef identity_conv
1741 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1743 static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
1744 &uvcg_default_color_matching_attr_b_color_primaries,
1745 &uvcg_default_color_matching_attr_b_transfer_characteristics,
1746 &uvcg_default_color_matching_attr_b_matrix_coefficients,
1750 static const struct config_item_type uvcg_default_color_matching_type = {
1751 .ct_attrs = uvcg_default_color_matching_attrs,
1752 .ct_owner = THIS_MODULE,
1755 /* struct uvcg_color_matching {}; */
1757 /* streaming/color_matching */
1758 static struct uvcg_color_matching_grp {
1759 struct config_group group;
1760 } uvcg_color_matching_grp;
1762 static const struct config_item_type uvcg_color_matching_grp_type = {
1763 .ct_owner = THIS_MODULE,
1766 /* streaming/class/{fs|hs|ss} */
1767 static struct uvcg_streaming_class {
1768 struct config_group group;
1769 } uvcg_streaming_class_fs, uvcg_streaming_class_hs, uvcg_streaming_class_ss;
1772 static inline struct uvc_descriptor_header
1773 ***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
1775 struct uvcg_streaming_class *cl = container_of(to_config_group(i),
1776 struct uvcg_streaming_class, group);
1778 if (cl == &uvcg_streaming_class_fs)
1779 return &o->uvc_fs_streaming_cls;
1781 if (cl == &uvcg_streaming_class_hs)
1782 return &o->uvc_hs_streaming_cls;
1784 if (cl == &uvcg_streaming_class_ss)
1785 return &o->uvc_ss_streaming_cls;
1790 enum uvcg_strm_type {
1797 * Iterate over a hierarchy of streaming descriptors' config items.
1798 * The items are created by the user with configfs.
1800 * It "processes" the header pointed to by @priv1, then for each format
1801 * that follows the header "processes" the format itself and then for
1802 * each frame inside a format "processes" the frame.
1804 * As a "processing" function the @fun is used.
1806 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
1807 * the amount of memory needed for an array of streaming descriptors
1808 * and second, to actually fill the array.
1810 * @h: streaming header pointer
1811 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
1812 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
1813 * @fun: callback function for processing each level of the hierarchy
1815 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
1816 void *priv2, void *priv3,
1817 int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type))
1819 struct uvcg_format_ptr *f;
1820 struct config_group *grp;
1821 struct config_item *item;
1822 struct uvcg_frame *frm;
1829 ret = fun(h, priv2, priv3, 0, UVCG_HEADER);
1832 list_for_each_entry(f, &h->formats, entry) {
1833 ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT);
1836 grp = &f->fmt->group;
1837 list_for_each_entry(item, &grp->cg_children, ci_entry) {
1838 frm = to_uvcg_frame(item);
1839 ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
1849 * Count how many bytes are needed for an array of streaming descriptors.
1851 * @priv1: pointer to a header, format or frame
1852 * @priv2: inout parameter, accumulated size of the array
1853 * @priv3: inout parameter, accumulated number of the array elements
1854 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
1856 static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
1857 enum uvcg_strm_type type)
1859 size_t *size = priv2;
1860 size_t *count = priv3;
1864 struct uvcg_streaming_header *h = priv1;
1866 *size += sizeof(h->desc);
1868 *size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE;
1872 struct uvcg_format *fmt = priv1;
1874 if (fmt->type == UVCG_UNCOMPRESSED) {
1875 struct uvcg_uncompressed *u =
1876 container_of(fmt, struct uvcg_uncompressed,
1879 *size += sizeof(u->desc);
1880 } else if (fmt->type == UVCG_MJPEG) {
1881 struct uvcg_mjpeg *m =
1882 container_of(fmt, struct uvcg_mjpeg, fmt);
1884 *size += sizeof(m->desc);
1891 struct uvcg_frame *frm = priv1;
1892 int sz = sizeof(frm->dw_frame_interval);
1894 *size += sizeof(frm->frame);
1895 *size += frm->frame.b_frame_interval_type * sz;
1906 * Fill an array of streaming descriptors.
1908 * @priv1: pointer to a header, format or frame
1909 * @priv2: inout parameter, pointer into a block of memory
1910 * @priv3: inout parameter, pointer to a 2-dimensional array
1912 static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
1913 enum uvcg_strm_type type)
1915 void **dest = priv2;
1916 struct uvc_descriptor_header ***array = priv3;
1924 struct uvc_input_header_descriptor *ihdr = *dest;
1925 struct uvcg_streaming_header *h = priv1;
1926 struct uvcg_format_ptr *f;
1928 memcpy(*dest, &h->desc, sizeof(h->desc));
1929 *dest += sizeof(h->desc);
1930 sz = UVCG_STREAMING_CONTROL_SIZE;
1931 list_for_each_entry(f, &h->formats, entry) {
1932 memcpy(*dest, f->fmt->bmaControls, sz);
1935 ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz;
1936 ihdr->bNumFormats = h->num_fmt;
1940 struct uvcg_format *fmt = priv1;
1942 if (fmt->type == UVCG_UNCOMPRESSED) {
1943 struct uvc_format_uncompressed *unc = *dest;
1944 struct uvcg_uncompressed *u =
1945 container_of(fmt, struct uvcg_uncompressed,
1948 memcpy(*dest, &u->desc, sizeof(u->desc));
1949 *dest += sizeof(u->desc);
1950 unc->bNumFrameDescriptors = fmt->num_frames;
1951 unc->bFormatIndex = n + 1;
1952 } else if (fmt->type == UVCG_MJPEG) {
1953 struct uvc_format_mjpeg *mjp = *dest;
1954 struct uvcg_mjpeg *m =
1955 container_of(fmt, struct uvcg_mjpeg, fmt);
1957 memcpy(*dest, &m->desc, sizeof(m->desc));
1958 *dest += sizeof(m->desc);
1959 mjp->bNumFrameDescriptors = fmt->num_frames;
1960 mjp->bFormatIndex = n + 1;
1967 struct uvcg_frame *frm = priv1;
1968 struct uvc_descriptor_header *h = *dest;
1970 sz = sizeof(frm->frame);
1971 memcpy(*dest, &frm->frame, sz);
1973 sz = frm->frame.b_frame_interval_type *
1974 sizeof(*frm->dw_frame_interval);
1975 memcpy(*dest, frm->dw_frame_interval, sz);
1977 if (frm->fmt_type == UVCG_UNCOMPRESSED)
1978 h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
1979 frm->frame.b_frame_interval_type);
1980 else if (frm->fmt_type == UVCG_MJPEG)
1981 h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
1982 frm->frame.b_frame_interval_type);
1990 static int uvcg_streaming_class_allow_link(struct config_item *src,
1991 struct config_item *target)
1993 struct config_item *streaming, *header;
1994 struct f_uvc_opts *opts;
1995 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1996 struct uvc_descriptor_header ***class_array, **cl_arr;
1997 struct uvcg_streaming_header *target_hdr;
1998 void *data, *data_save;
1999 size_t size = 0, count = 0;
2002 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2004 streaming = src->ci_parent->ci_parent;
2005 header = config_group_find_item(to_config_group(streaming), "header");
2006 if (!header || target->ci_parent != header)
2009 opts = to_f_uvc_opts(streaming->ci_parent);
2011 mutex_lock(&opts->lock);
2013 class_array = __uvcg_get_stream_class_arr(src, opts);
2014 if (!class_array || *class_array || opts->refcnt) {
2019 target_hdr = to_uvcg_streaming_header(target);
2020 ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm);
2024 count += 2; /* color_matching, NULL */
2025 *class_array = kcalloc(count, sizeof(void *), GFP_KERNEL);
2026 if (!*class_array) {
2031 data = data_save = kzalloc(size, GFP_KERNEL);
2033 kfree(*class_array);
2034 *class_array = NULL;
2038 cl_arr = *class_array;
2039 ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr,
2042 kfree(*class_array);
2043 *class_array = NULL;
2045 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2046 * might have advanced the "data", so use a backup copy
2051 *cl_arr = (struct uvc_descriptor_header *)&opts->uvc_color_matching;
2053 ++target_hdr->linked;
2057 mutex_unlock(&opts->lock);
2059 config_item_put(header);
2060 mutex_unlock(su_mutex);
2064 static void uvcg_streaming_class_drop_link(struct config_item *src,
2065 struct config_item *target)
2067 struct config_item *streaming, *header;
2068 struct f_uvc_opts *opts;
2069 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2070 struct uvc_descriptor_header ***class_array;
2071 struct uvcg_streaming_header *target_hdr;
2073 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2075 streaming = src->ci_parent->ci_parent;
2076 header = config_group_find_item(to_config_group(streaming), "header");
2077 if (!header || target->ci_parent != header)
2080 opts = to_f_uvc_opts(streaming->ci_parent);
2082 mutex_lock(&opts->lock);
2084 class_array = __uvcg_get_stream_class_arr(src, opts);
2085 if (!class_array || !*class_array)
2091 target_hdr = to_uvcg_streaming_header(target);
2092 --target_hdr->linked;
2093 kfree(**class_array);
2094 kfree(*class_array);
2095 *class_array = NULL;
2098 mutex_unlock(&opts->lock);
2100 config_item_put(header);
2101 mutex_unlock(su_mutex);
2104 static struct configfs_item_operations uvcg_streaming_class_item_ops = {
2105 .allow_link = uvcg_streaming_class_allow_link,
2106 .drop_link = uvcg_streaming_class_drop_link,
2109 static const struct config_item_type uvcg_streaming_class_type = {
2110 .ct_item_ops = &uvcg_streaming_class_item_ops,
2111 .ct_owner = THIS_MODULE,
2114 /* streaming/class */
2115 static struct uvcg_streaming_class_grp {
2116 struct config_group group;
2117 } uvcg_streaming_class_grp;
2119 static const struct config_item_type uvcg_streaming_class_grp_type = {
2120 .ct_owner = THIS_MODULE,
2124 static struct uvcg_streaming_grp {
2125 struct config_group group;
2126 } uvcg_streaming_grp;
2128 static const struct config_item_type uvcg_streaming_grp_type = {
2129 .ct_owner = THIS_MODULE,
2132 static void uvc_attr_release(struct config_item *item)
2134 struct f_uvc_opts *opts = to_f_uvc_opts(item);
2136 usb_put_function_instance(&opts->func_inst);
2139 static struct configfs_item_operations uvc_item_ops = {
2140 .release = uvc_attr_release,
2143 #define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
2144 static ssize_t f_uvc_opts_##cname##_show( \
2145 struct config_item *item, char *page) \
2147 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2150 mutex_lock(&opts->lock); \
2151 result = sprintf(page, "%d\n", conv(opts->cname)); \
2152 mutex_unlock(&opts->lock); \
2158 f_uvc_opts_##cname##_store(struct config_item *item, \
2159 const char *page, size_t len) \
2161 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2165 mutex_lock(&opts->lock); \
2166 if (opts->refcnt) { \
2171 ret = str2u(page, 0, &num); \
2175 if (num > limit) { \
2179 opts->cname = vnoc(num); \
2182 mutex_unlock(&opts->lock); \
2186 UVC_ATTR(f_uvc_opts_, cname, cname)
2188 #define identity_conv(x) (x)
2190 UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv,
2191 kstrtou8, u8, identity_conv, 16);
2192 UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu,
2193 kstrtou16, u16, le16_to_cpu, 3072);
2194 UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv,
2195 kstrtou8, u8, identity_conv, 15);
2197 #undef identity_conv
2199 #undef UVCG_OPTS_ATTR
2201 static struct configfs_attribute *uvc_attrs[] = {
2202 &f_uvc_opts_attr_streaming_interval,
2203 &f_uvc_opts_attr_streaming_maxpacket,
2204 &f_uvc_opts_attr_streaming_maxburst,
2208 static const struct config_item_type uvc_func_type = {
2209 .ct_item_ops = &uvc_item_ops,
2210 .ct_attrs = uvc_attrs,
2211 .ct_owner = THIS_MODULE,
2214 int uvcg_attach_configfs(struct f_uvc_opts *opts)
2216 config_group_init_type_name(&uvcg_control_header_grp.group,
2218 &uvcg_control_header_grp_type);
2220 config_group_init_type_name(&uvcg_default_processing.group,
2221 "default", &uvcg_default_processing_type);
2222 config_group_init_type_name(&uvcg_processing_grp.group,
2223 "processing", &uvcg_processing_grp_type);
2224 configfs_add_default_group(&uvcg_default_processing.group,
2225 &uvcg_processing_grp.group);
2227 config_group_init_type_name(&uvcg_default_camera.group,
2228 "default", &uvcg_default_camera_type);
2229 config_group_init_type_name(&uvcg_camera_grp.group,
2230 "camera", &uvcg_camera_grp_type);
2231 configfs_add_default_group(&uvcg_default_camera.group,
2232 &uvcg_camera_grp.group);
2234 config_group_init_type_name(&uvcg_default_output.group,
2235 "default", &uvcg_default_output_type);
2236 config_group_init_type_name(&uvcg_output_grp.group,
2237 "output", &uvcg_output_grp_type);
2238 configfs_add_default_group(&uvcg_default_output.group,
2239 &uvcg_output_grp.group);
2241 config_group_init_type_name(&uvcg_terminal_grp.group,
2242 "terminal", &uvcg_terminal_grp_type);
2243 configfs_add_default_group(&uvcg_camera_grp.group,
2244 &uvcg_terminal_grp.group);
2245 configfs_add_default_group(&uvcg_output_grp.group,
2246 &uvcg_terminal_grp.group);
2248 config_group_init_type_name(&uvcg_control_class_fs.group,
2249 "fs", &uvcg_control_class_type);
2250 config_group_init_type_name(&uvcg_control_class_ss.group,
2251 "ss", &uvcg_control_class_type);
2252 config_group_init_type_name(&uvcg_control_class_grp.group,
2254 &uvcg_control_class_grp_type);
2255 configfs_add_default_group(&uvcg_control_class_fs.group,
2256 &uvcg_control_class_grp.group);
2257 configfs_add_default_group(&uvcg_control_class_ss.group,
2258 &uvcg_control_class_grp.group);
2260 config_group_init_type_name(&uvcg_control_grp.group,
2262 &uvcg_control_grp_type);
2263 configfs_add_default_group(&uvcg_control_header_grp.group,
2264 &uvcg_control_grp.group);
2265 configfs_add_default_group(&uvcg_processing_grp.group,
2266 &uvcg_control_grp.group);
2267 configfs_add_default_group(&uvcg_terminal_grp.group,
2268 &uvcg_control_grp.group);
2269 configfs_add_default_group(&uvcg_control_class_grp.group,
2270 &uvcg_control_grp.group);
2272 config_group_init_type_name(&uvcg_streaming_header_grp.group,
2274 &uvcg_streaming_header_grp_type);
2275 config_group_init_type_name(&uvcg_uncompressed_grp.group,
2277 &uvcg_uncompressed_grp_type);
2278 config_group_init_type_name(&uvcg_mjpeg_grp.group,
2280 &uvcg_mjpeg_grp_type);
2281 config_group_init_type_name(&uvcg_default_color_matching.group,
2283 &uvcg_default_color_matching_type);
2284 config_group_init_type_name(&uvcg_color_matching_grp.group,
2286 &uvcg_color_matching_grp_type);
2287 configfs_add_default_group(&uvcg_default_color_matching.group,
2288 &uvcg_color_matching_grp.group);
2290 config_group_init_type_name(&uvcg_streaming_class_fs.group,
2291 "fs", &uvcg_streaming_class_type);
2292 config_group_init_type_name(&uvcg_streaming_class_hs.group,
2293 "hs", &uvcg_streaming_class_type);
2294 config_group_init_type_name(&uvcg_streaming_class_ss.group,
2295 "ss", &uvcg_streaming_class_type);
2296 config_group_init_type_name(&uvcg_streaming_class_grp.group,
2297 "class", &uvcg_streaming_class_grp_type);
2298 configfs_add_default_group(&uvcg_streaming_class_fs.group,
2299 &uvcg_streaming_class_grp.group);
2300 configfs_add_default_group(&uvcg_streaming_class_hs.group,
2301 &uvcg_streaming_class_grp.group);
2302 configfs_add_default_group(&uvcg_streaming_class_ss.group,
2303 &uvcg_streaming_class_grp.group);
2305 config_group_init_type_name(&uvcg_streaming_grp.group,
2306 "streaming", &uvcg_streaming_grp_type);
2307 configfs_add_default_group(&uvcg_streaming_header_grp.group,
2308 &uvcg_streaming_grp.group);
2309 configfs_add_default_group(&uvcg_uncompressed_grp.group,
2310 &uvcg_streaming_grp.group);
2311 configfs_add_default_group(&uvcg_mjpeg_grp.group,
2312 &uvcg_streaming_grp.group);
2313 configfs_add_default_group(&uvcg_color_matching_grp.group,
2314 &uvcg_streaming_grp.group);
2315 configfs_add_default_group(&uvcg_streaming_class_grp.group,
2316 &uvcg_streaming_grp.group);
2318 config_group_init_type_name(&opts->func_inst.group,
2321 configfs_add_default_group(&uvcg_control_grp.group,
2322 &opts->func_inst.group);
2323 configfs_add_default_group(&uvcg_streaming_grp.group,
2324 &opts->func_inst.group);