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 <andrzejtp2010@gmail.com>
13 #include "uvc_configfs.h"
15 #include <linux/sort.h>
17 /* -----------------------------------------------------------------------------
18 * Global Utility Structures and Macros
21 #define UVC_ATTR(prefix, cname, aname) \
22 static struct configfs_attribute prefix##attr_##cname = { \
23 .ca_name = __stringify(aname), \
24 .ca_mode = S_IRUGO | S_IWUGO, \
25 .ca_owner = THIS_MODULE, \
26 .show = prefix##cname##_show, \
27 .store = prefix##cname##_store, \
30 #define UVC_ATTR_RO(prefix, cname, aname) \
31 static struct configfs_attribute prefix##attr_##cname = { \
32 .ca_name = __stringify(aname), \
34 .ca_owner = THIS_MODULE, \
35 .show = prefix##cname##_show, \
38 #define le8_to_cpu(x) (x)
39 #define cpu_to_le8(x) (x)
41 static int uvcg_config_compare_u32(const void *l, const void *r)
43 u32 li = *(const u32 *)l;
44 u32 ri = *(const u32 *)r;
46 return li < ri ? -1 : li == ri ? 0 : 1;
49 struct uvcg_config_group_type {
50 struct config_item_type type;
52 const struct uvcg_config_group_type **children;
53 int (*create_children)(struct config_group *group);
56 static void uvcg_config_item_release(struct config_item *item)
58 struct config_group *group = to_config_group(item);
63 static struct configfs_item_operations uvcg_config_item_ops = {
64 .release = uvcg_config_item_release,
67 static int uvcg_config_create_group(struct config_group *parent,
68 const struct uvcg_config_group_type *type);
70 static int uvcg_config_create_children(struct config_group *group,
71 const struct uvcg_config_group_type *type)
73 const struct uvcg_config_group_type **child;
76 if (type->create_children)
77 return type->create_children(group);
79 for (child = type->children; child && *child; ++child) {
80 ret = uvcg_config_create_group(group, *child);
88 static int uvcg_config_create_group(struct config_group *parent,
89 const struct uvcg_config_group_type *type)
91 struct config_group *group;
93 group = kzalloc(sizeof(*group), GFP_KERNEL);
97 config_group_init_type_name(group, type->name, &type->type);
98 configfs_add_default_group(group, parent);
100 return uvcg_config_create_children(group, type);
103 static void uvcg_config_remove_children(struct config_group *group)
105 struct config_group *child, *n;
107 list_for_each_entry_safe(child, n, &group->default_groups, group_entry) {
108 list_del(&child->group_entry);
109 uvcg_config_remove_children(child);
110 config_item_put(&child->cg_item);
114 /* -----------------------------------------------------------------------------
115 * control/header/<NAME>
119 #define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \
120 static ssize_t uvcg_control_header_##cname##_show( \
121 struct config_item *item, char *page) \
123 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
124 struct f_uvc_opts *opts; \
125 struct config_item *opts_item; \
126 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
129 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
131 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
132 opts = to_f_uvc_opts(opts_item); \
134 mutex_lock(&opts->lock); \
135 result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\
136 mutex_unlock(&opts->lock); \
138 mutex_unlock(su_mutex); \
143 uvcg_control_header_##cname##_store(struct config_item *item, \
144 const char *page, size_t len) \
146 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
147 struct f_uvc_opts *opts; \
148 struct config_item *opts_item; \
149 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
153 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
155 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
156 opts = to_f_uvc_opts(opts_item); \
158 mutex_lock(&opts->lock); \
159 if (ch->linked || opts->refcnt) { \
164 ret = kstrtou##bits(page, 0, &num); \
172 ch->desc.aname = cpu_to_le##bits(num); \
175 mutex_unlock(&opts->lock); \
176 mutex_unlock(su_mutex); \
180 UVC_ATTR(uvcg_control_header_, cname, aname)
182 UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, 16, 0xffff);
184 UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, 32, 0x7fffffff);
186 #undef UVCG_CTRL_HDR_ATTR
188 static struct configfs_attribute *uvcg_control_header_attrs[] = {
189 &uvcg_control_header_attr_bcd_uvc,
190 &uvcg_control_header_attr_dw_clock_frequency,
194 static const struct config_item_type uvcg_control_header_type = {
195 .ct_item_ops = &uvcg_config_item_ops,
196 .ct_attrs = uvcg_control_header_attrs,
197 .ct_owner = THIS_MODULE,
200 static struct config_item *uvcg_control_header_make(struct config_group *group,
203 struct uvcg_control_header *h;
205 h = kzalloc(sizeof(*h), GFP_KERNEL);
207 return ERR_PTR(-ENOMEM);
209 h->desc.bLength = UVC_DT_HEADER_SIZE(1);
210 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
211 h->desc.bDescriptorSubType = UVC_VC_HEADER;
212 h->desc.bcdUVC = cpu_to_le16(0x0110);
213 h->desc.dwClockFrequency = cpu_to_le32(48000000);
215 config_item_init_type_name(&h->item, name, &uvcg_control_header_type);
220 static struct configfs_group_operations uvcg_control_header_grp_ops = {
221 .make_item = uvcg_control_header_make,
224 static const struct uvcg_config_group_type uvcg_control_header_grp_type = {
226 .ct_item_ops = &uvcg_config_item_ops,
227 .ct_group_ops = &uvcg_control_header_grp_ops,
228 .ct_owner = THIS_MODULE,
233 /* -----------------------------------------------------------------------------
234 * control/processing/default
237 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, bits) \
238 static ssize_t uvcg_default_processing_##cname##_show( \
239 struct config_item *item, char *page) \
241 struct config_group *group = to_config_group(item); \
242 struct f_uvc_opts *opts; \
243 struct config_item *opts_item; \
244 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
245 struct uvc_processing_unit_descriptor *pd; \
248 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
250 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
251 opts = to_f_uvc_opts(opts_item); \
252 pd = &opts->uvc_processing; \
254 mutex_lock(&opts->lock); \
255 result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \
256 mutex_unlock(&opts->lock); \
258 mutex_unlock(su_mutex); \
262 UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
264 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, 8);
265 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, 8);
266 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, 16);
267 UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8);
269 #undef UVCG_DEFAULT_PROCESSING_ATTR
271 static ssize_t uvcg_default_processing_bm_controls_show(
272 struct config_item *item, char *page)
274 struct config_group *group = to_config_group(item);
275 struct f_uvc_opts *opts;
276 struct config_item *opts_item;
277 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
278 struct uvc_processing_unit_descriptor *pd;
282 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
284 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
285 opts = to_f_uvc_opts(opts_item);
286 pd = &opts->uvc_processing;
288 mutex_lock(&opts->lock);
289 for (result = 0, i = 0; i < pd->bControlSize; ++i) {
290 result += sprintf(pg, "%u\n", pd->bmControls[i]);
293 mutex_unlock(&opts->lock);
295 mutex_unlock(su_mutex);
300 UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
302 static struct configfs_attribute *uvcg_default_processing_attrs[] = {
303 &uvcg_default_processing_attr_b_unit_id,
304 &uvcg_default_processing_attr_b_source_id,
305 &uvcg_default_processing_attr_w_max_multiplier,
306 &uvcg_default_processing_attr_bm_controls,
307 &uvcg_default_processing_attr_i_processing,
311 static const struct uvcg_config_group_type uvcg_default_processing_type = {
313 .ct_item_ops = &uvcg_config_item_ops,
314 .ct_attrs = uvcg_default_processing_attrs,
315 .ct_owner = THIS_MODULE,
320 /* -----------------------------------------------------------------------------
324 static const struct uvcg_config_group_type uvcg_processing_grp_type = {
326 .ct_item_ops = &uvcg_config_item_ops,
327 .ct_owner = THIS_MODULE,
329 .name = "processing",
330 .children = (const struct uvcg_config_group_type*[]) {
331 &uvcg_default_processing_type,
336 /* -----------------------------------------------------------------------------
337 * control/terminal/camera/default
340 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, bits) \
341 static ssize_t uvcg_default_camera_##cname##_show( \
342 struct config_item *item, char *page) \
344 struct config_group *group = to_config_group(item); \
345 struct f_uvc_opts *opts; \
346 struct config_item *opts_item; \
347 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
348 struct uvc_camera_terminal_descriptor *cd; \
351 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
353 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \
355 opts = to_f_uvc_opts(opts_item); \
356 cd = &opts->uvc_camera_terminal; \
358 mutex_lock(&opts->lock); \
359 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
360 mutex_unlock(&opts->lock); \
362 mutex_unlock(su_mutex); \
367 UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
369 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, 8);
370 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, 16);
371 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, 8);
372 UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, 8);
373 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
375 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
377 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
380 #undef UVCG_DEFAULT_CAMERA_ATTR
382 static ssize_t uvcg_default_camera_bm_controls_show(
383 struct config_item *item, char *page)
385 struct config_group *group = to_config_group(item);
386 struct f_uvc_opts *opts;
387 struct config_item *opts_item;
388 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
389 struct uvc_camera_terminal_descriptor *cd;
393 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
395 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
397 opts = to_f_uvc_opts(opts_item);
398 cd = &opts->uvc_camera_terminal;
400 mutex_lock(&opts->lock);
401 for (result = 0, i = 0; i < cd->bControlSize; ++i) {
402 result += sprintf(pg, "%u\n", cd->bmControls[i]);
405 mutex_unlock(&opts->lock);
407 mutex_unlock(su_mutex);
411 UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
413 static struct configfs_attribute *uvcg_default_camera_attrs[] = {
414 &uvcg_default_camera_attr_b_terminal_id,
415 &uvcg_default_camera_attr_w_terminal_type,
416 &uvcg_default_camera_attr_b_assoc_terminal,
417 &uvcg_default_camera_attr_i_terminal,
418 &uvcg_default_camera_attr_w_objective_focal_length_min,
419 &uvcg_default_camera_attr_w_objective_focal_length_max,
420 &uvcg_default_camera_attr_w_ocular_focal_length,
421 &uvcg_default_camera_attr_bm_controls,
425 static const struct uvcg_config_group_type uvcg_default_camera_type = {
427 .ct_item_ops = &uvcg_config_item_ops,
428 .ct_attrs = uvcg_default_camera_attrs,
429 .ct_owner = THIS_MODULE,
434 /* -----------------------------------------------------------------------------
435 * control/terminal/camera
438 static const struct uvcg_config_group_type uvcg_camera_grp_type = {
440 .ct_item_ops = &uvcg_config_item_ops,
441 .ct_owner = THIS_MODULE,
444 .children = (const struct uvcg_config_group_type*[]) {
445 &uvcg_default_camera_type,
450 /* -----------------------------------------------------------------------------
451 * control/terminal/output/default
454 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, bits) \
455 static ssize_t uvcg_default_output_##cname##_show( \
456 struct config_item *item, char *page) \
458 struct config_group *group = to_config_group(item); \
459 struct f_uvc_opts *opts; \
460 struct config_item *opts_item; \
461 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
462 struct uvc_output_terminal_descriptor *cd; \
465 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
467 opts_item = group->cg_item.ci_parent->ci_parent-> \
468 ci_parent->ci_parent; \
469 opts = to_f_uvc_opts(opts_item); \
470 cd = &opts->uvc_output_terminal; \
472 mutex_lock(&opts->lock); \
473 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
474 mutex_unlock(&opts->lock); \
476 mutex_unlock(su_mutex); \
481 UVC_ATTR_RO(uvcg_default_output_, cname, aname)
483 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, 8);
484 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, 16);
485 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, 8);
486 UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, 8);
487 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, 8);
489 #undef UVCG_DEFAULT_OUTPUT_ATTR
491 static struct configfs_attribute *uvcg_default_output_attrs[] = {
492 &uvcg_default_output_attr_b_terminal_id,
493 &uvcg_default_output_attr_w_terminal_type,
494 &uvcg_default_output_attr_b_assoc_terminal,
495 &uvcg_default_output_attr_b_source_id,
496 &uvcg_default_output_attr_i_terminal,
500 static const struct uvcg_config_group_type uvcg_default_output_type = {
502 .ct_item_ops = &uvcg_config_item_ops,
503 .ct_attrs = uvcg_default_output_attrs,
504 .ct_owner = THIS_MODULE,
509 /* -----------------------------------------------------------------------------
510 * control/terminal/output
513 static const struct uvcg_config_group_type uvcg_output_grp_type = {
515 .ct_item_ops = &uvcg_config_item_ops,
516 .ct_owner = THIS_MODULE,
519 .children = (const struct uvcg_config_group_type*[]) {
520 &uvcg_default_output_type,
525 /* -----------------------------------------------------------------------------
529 static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
531 .ct_item_ops = &uvcg_config_item_ops,
532 .ct_owner = THIS_MODULE,
535 .children = (const struct uvcg_config_group_type*[]) {
536 &uvcg_camera_grp_type,
537 &uvcg_output_grp_type,
542 /* -----------------------------------------------------------------------------
543 * control/class/{fs|ss}
546 struct uvcg_control_class_group {
547 struct config_group group;
551 static inline struct uvc_descriptor_header
552 **uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
554 struct uvcg_control_class_group *group =
555 container_of(i, struct uvcg_control_class_group,
558 if (!strcmp(group->name, "fs"))
559 return o->uvc_fs_control_cls;
561 if (!strcmp(group->name, "ss"))
562 return o->uvc_ss_control_cls;
567 static int uvcg_control_class_allow_link(struct config_item *src,
568 struct config_item *target)
570 struct config_item *control, *header;
571 struct f_uvc_opts *opts;
572 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
573 struct uvc_descriptor_header **class_array;
574 struct uvcg_control_header *target_hdr;
577 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
579 control = src->ci_parent->ci_parent;
580 header = config_group_find_item(to_config_group(control), "header");
581 if (!header || target->ci_parent != header)
584 opts = to_f_uvc_opts(control->ci_parent);
586 mutex_lock(&opts->lock);
588 class_array = uvcg_get_ctl_class_arr(src, opts);
591 if (opts->refcnt || class_array[0]) {
596 target_hdr = to_uvcg_control_header(target);
597 ++target_hdr->linked;
598 class_array[0] = (struct uvc_descriptor_header *)&target_hdr->desc;
602 mutex_unlock(&opts->lock);
604 config_item_put(header);
605 mutex_unlock(su_mutex);
609 static void uvcg_control_class_drop_link(struct config_item *src,
610 struct config_item *target)
612 struct config_item *control, *header;
613 struct f_uvc_opts *opts;
614 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
615 struct uvc_descriptor_header **class_array;
616 struct uvcg_control_header *target_hdr;
618 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
620 control = src->ci_parent->ci_parent;
621 header = config_group_find_item(to_config_group(control), "header");
622 if (!header || target->ci_parent != header)
625 opts = to_f_uvc_opts(control->ci_parent);
627 mutex_lock(&opts->lock);
629 class_array = uvcg_get_ctl_class_arr(src, opts);
630 if (!class_array || opts->refcnt)
633 target_hdr = to_uvcg_control_header(target);
634 --target_hdr->linked;
635 class_array[0] = NULL;
638 mutex_unlock(&opts->lock);
640 config_item_put(header);
641 mutex_unlock(su_mutex);
644 static struct configfs_item_operations uvcg_control_class_item_ops = {
645 .release = uvcg_config_item_release,
646 .allow_link = uvcg_control_class_allow_link,
647 .drop_link = uvcg_control_class_drop_link,
650 static const struct config_item_type uvcg_control_class_type = {
651 .ct_item_ops = &uvcg_control_class_item_ops,
652 .ct_owner = THIS_MODULE,
655 /* -----------------------------------------------------------------------------
659 static int uvcg_control_class_create_children(struct config_group *parent)
661 static const char * const names[] = { "fs", "ss" };
664 for (i = 0; i < ARRAY_SIZE(names); ++i) {
665 struct uvcg_control_class_group *group;
667 group = kzalloc(sizeof(*group), GFP_KERNEL);
671 group->name = names[i];
673 config_group_init_type_name(&group->group, group->name,
674 &uvcg_control_class_type);
675 configfs_add_default_group(&group->group, parent);
681 static const struct uvcg_config_group_type uvcg_control_class_grp_type = {
683 .ct_item_ops = &uvcg_config_item_ops,
684 .ct_owner = THIS_MODULE,
687 .create_children = uvcg_control_class_create_children,
690 /* -----------------------------------------------------------------------------
694 static ssize_t uvcg_default_control_b_interface_number_show(
695 struct config_item *item, char *page)
697 struct config_group *group = to_config_group(item);
698 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
699 struct config_item *opts_item;
700 struct f_uvc_opts *opts;
703 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
705 opts_item = item->ci_parent;
706 opts = to_f_uvc_opts(opts_item);
708 mutex_lock(&opts->lock);
709 result += sprintf(page, "%u\n", opts->control_interface);
710 mutex_unlock(&opts->lock);
712 mutex_unlock(su_mutex);
717 UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
719 static struct configfs_attribute *uvcg_default_control_attrs[] = {
720 &uvcg_default_control_attr_b_interface_number,
724 static const struct uvcg_config_group_type uvcg_control_grp_type = {
726 .ct_item_ops = &uvcg_config_item_ops,
727 .ct_attrs = uvcg_default_control_attrs,
728 .ct_owner = THIS_MODULE,
731 .children = (const struct uvcg_config_group_type*[]) {
732 &uvcg_control_header_grp_type,
733 &uvcg_processing_grp_type,
734 &uvcg_terminal_grp_type,
735 &uvcg_control_class_grp_type,
740 /* -----------------------------------------------------------------------------
741 * streaming/uncompressed
745 static const char * const uvcg_format_names[] = {
750 static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
752 struct f_uvc_opts *opts;
753 struct config_item *opts_item;
754 struct mutex *su_mutex = &f->group.cg_subsys->su_mutex;
758 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
760 opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
761 opts = to_f_uvc_opts(opts_item);
763 mutex_lock(&opts->lock);
764 result = sprintf(pg, "0x");
766 for (i = 0; i < UVCG_STREAMING_CONTROL_SIZE; ++i) {
767 result += sprintf(pg, "%x\n", f->bmaControls[i]);
770 mutex_unlock(&opts->lock);
772 mutex_unlock(su_mutex);
776 static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
777 const char *page, size_t len)
779 struct f_uvc_opts *opts;
780 struct config_item *opts_item;
781 struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex;
784 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
786 opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent;
787 opts = to_f_uvc_opts(opts_item);
789 mutex_lock(&opts->lock);
790 if (ch->linked || opts->refcnt) {
795 if (len < 4 || *page != '0' ||
796 (*(page + 1) != 'x' && *(page + 1) != 'X'))
798 ret = hex2bin(ch->bmaControls, page + 2, 1);
803 mutex_unlock(&opts->lock);
804 mutex_unlock(su_mutex);
808 /* -----------------------------------------------------------------------------
809 * streaming/header/<NAME>
813 static void uvcg_format_set_indices(struct config_group *fmt);
815 static int uvcg_streaming_header_allow_link(struct config_item *src,
816 struct config_item *target)
818 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
819 struct config_item *opts_item;
820 struct f_uvc_opts *opts;
821 struct uvcg_streaming_header *src_hdr;
822 struct uvcg_format *target_fmt = NULL;
823 struct uvcg_format_ptr *format_ptr;
824 int i, ret = -EINVAL;
826 src_hdr = to_uvcg_streaming_header(src);
827 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
829 opts_item = src->ci_parent->ci_parent->ci_parent;
830 opts = to_f_uvc_opts(opts_item);
832 mutex_lock(&opts->lock);
834 if (src_hdr->linked) {
840 * Linking is only allowed to direct children of the format nodes
841 * (streaming/uncompressed or streaming/mjpeg nodes). First check that
842 * the grand-parent of the target matches the grand-parent of the source
843 * (the streaming node), and then verify that the target parent is a
846 if (src->ci_parent->ci_parent != target->ci_parent->ci_parent)
849 for (i = 0; i < ARRAY_SIZE(uvcg_format_names); ++i) {
850 if (!strcmp(target->ci_parent->ci_name, uvcg_format_names[i]))
854 if (i == ARRAY_SIZE(uvcg_format_names))
857 target_fmt = container_of(to_config_group(target), struct uvcg_format,
860 uvcg_format_set_indices(to_config_group(target));
862 format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
868 format_ptr->fmt = target_fmt;
869 list_add_tail(&format_ptr->entry, &src_hdr->formats);
871 ++target_fmt->linked;
874 mutex_unlock(&opts->lock);
875 mutex_unlock(su_mutex);
879 static void uvcg_streaming_header_drop_link(struct config_item *src,
880 struct config_item *target)
882 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
883 struct config_item *opts_item;
884 struct f_uvc_opts *opts;
885 struct uvcg_streaming_header *src_hdr;
886 struct uvcg_format *target_fmt = NULL;
887 struct uvcg_format_ptr *format_ptr, *tmp;
889 src_hdr = to_uvcg_streaming_header(src);
890 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
892 opts_item = src->ci_parent->ci_parent->ci_parent;
893 opts = to_f_uvc_opts(opts_item);
895 mutex_lock(&opts->lock);
896 target_fmt = container_of(to_config_group(target), struct uvcg_format,
899 list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
900 if (format_ptr->fmt == target_fmt) {
901 list_del(&format_ptr->entry);
907 --target_fmt->linked;
909 mutex_unlock(&opts->lock);
910 mutex_unlock(su_mutex);
913 static struct configfs_item_operations uvcg_streaming_header_item_ops = {
914 .release = uvcg_config_item_release,
915 .allow_link = uvcg_streaming_header_allow_link,
916 .drop_link = uvcg_streaming_header_drop_link,
919 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, bits) \
920 static ssize_t uvcg_streaming_header_##cname##_show( \
921 struct config_item *item, char *page) \
923 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
924 struct f_uvc_opts *opts; \
925 struct config_item *opts_item; \
926 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
929 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
931 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
932 opts = to_f_uvc_opts(opts_item); \
934 mutex_lock(&opts->lock); \
935 result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\
936 mutex_unlock(&opts->lock); \
938 mutex_unlock(su_mutex); \
942 UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
944 UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, 8);
945 UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, 8);
946 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, 8);
947 UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, 8);
948 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, 8);
950 #undef UVCG_STREAMING_HEADER_ATTR
952 static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
953 &uvcg_streaming_header_attr_bm_info,
954 &uvcg_streaming_header_attr_b_terminal_link,
955 &uvcg_streaming_header_attr_b_still_capture_method,
956 &uvcg_streaming_header_attr_b_trigger_support,
957 &uvcg_streaming_header_attr_b_trigger_usage,
961 static const struct config_item_type uvcg_streaming_header_type = {
962 .ct_item_ops = &uvcg_streaming_header_item_ops,
963 .ct_attrs = uvcg_streaming_header_attrs,
964 .ct_owner = THIS_MODULE,
967 static struct config_item
968 *uvcg_streaming_header_make(struct config_group *group, const char *name)
970 struct uvcg_streaming_header *h;
972 h = kzalloc(sizeof(*h), GFP_KERNEL);
974 return ERR_PTR(-ENOMEM);
976 INIT_LIST_HEAD(&h->formats);
977 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
978 h->desc.bDescriptorSubType = UVC_VS_INPUT_HEADER;
979 h->desc.bTerminalLink = 3;
980 h->desc.bControlSize = UVCG_STREAMING_CONTROL_SIZE;
982 config_item_init_type_name(&h->item, name, &uvcg_streaming_header_type);
987 static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
988 .make_item = uvcg_streaming_header_make,
991 static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = {
993 .ct_item_ops = &uvcg_config_item_ops,
994 .ct_group_ops = &uvcg_streaming_header_grp_ops,
995 .ct_owner = THIS_MODULE,
1000 /* -----------------------------------------------------------------------------
1001 * streaming/<mode>/<format>/<NAME>
1004 #define UVCG_FRAME_ATTR(cname, aname, bits) \
1005 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
1007 struct uvcg_frame *f = to_uvcg_frame(item); \
1008 struct f_uvc_opts *opts; \
1009 struct config_item *opts_item; \
1010 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1013 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1015 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1016 opts = to_f_uvc_opts(opts_item); \
1018 mutex_lock(&opts->lock); \
1019 result = sprintf(page, "%u\n", f->frame.cname); \
1020 mutex_unlock(&opts->lock); \
1022 mutex_unlock(su_mutex); \
1026 static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
1027 const char *page, size_t len)\
1029 struct uvcg_frame *f = to_uvcg_frame(item); \
1030 struct f_uvc_opts *opts; \
1031 struct config_item *opts_item; \
1032 struct uvcg_format *fmt; \
1033 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1034 typeof(f->frame.cname) num; \
1037 ret = kstrtou##bits(page, 0, &num); \
1041 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1043 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1044 opts = to_f_uvc_opts(opts_item); \
1045 fmt = to_uvcg_format(f->item.ci_parent); \
1047 mutex_lock(&opts->lock); \
1048 if (fmt->linked || opts->refcnt) { \
1053 f->frame.cname = num; \
1056 mutex_unlock(&opts->lock); \
1057 mutex_unlock(su_mutex); \
1061 UVC_ATTR(uvcg_frame_, cname, aname);
1063 static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
1066 struct uvcg_frame *f = to_uvcg_frame(item);
1067 struct uvcg_format *fmt;
1068 struct f_uvc_opts *opts;
1069 struct config_item *opts_item;
1070 struct config_item *fmt_item;
1071 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;
1074 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1076 fmt_item = f->item.ci_parent;
1077 fmt = to_uvcg_format(fmt_item);
1084 opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
1085 opts = to_f_uvc_opts(opts_item);
1087 mutex_lock(&opts->lock);
1088 result = sprintf(page, "%u\n", f->frame.b_frame_index);
1089 mutex_unlock(&opts->lock);
1092 mutex_unlock(su_mutex);
1096 UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
1098 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8);
1099 UVCG_FRAME_ATTR(w_width, wWidth, 16);
1100 UVCG_FRAME_ATTR(w_height, wHeight, 16);
1101 UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
1102 UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
1103 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
1104 UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
1106 #undef UVCG_FRAME_ATTR
1108 static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
1111 struct uvcg_frame *frm = to_uvcg_frame(item);
1112 struct f_uvc_opts *opts;
1113 struct config_item *opts_item;
1114 struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
1118 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1120 opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
1121 opts = to_f_uvc_opts(opts_item);
1123 mutex_lock(&opts->lock);
1124 for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
1125 result += sprintf(pg, "%u\n", frm->dw_frame_interval[i]);
1128 mutex_unlock(&opts->lock);
1130 mutex_unlock(su_mutex);
1134 static inline int __uvcg_count_frm_intrv(char *buf, void *priv)
1140 static inline int __uvcg_fill_frm_intrv(char *buf, void *priv)
1145 ret = kstrtou32(buf, 0, &num);
1156 static int __uvcg_iter_frm_intrv(const char *page, size_t len,
1157 int (*fun)(char *, void *), void *priv)
1159 /* sign, base 2 representation, newline, terminator */
1160 char buf[1 + sizeof(u32) * 8 + 1 + 1];
1161 const char *pg = page;
1167 while (pg - page < len) {
1169 while (i < sizeof(buf) && (pg - page < len) &&
1170 *pg != '\0' && *pg != '\n')
1172 if (i == sizeof(buf))
1174 while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
1177 ret = fun(buf, priv);
1185 static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
1186 const char *page, size_t len)
1188 struct uvcg_frame *ch = to_uvcg_frame(item);
1189 struct f_uvc_opts *opts;
1190 struct config_item *opts_item;
1191 struct uvcg_format *fmt;
1192 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
1194 u32 *frm_intrv, *tmp;
1196 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1198 opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
1199 opts = to_f_uvc_opts(opts_item);
1200 fmt = to_uvcg_format(ch->item.ci_parent);
1202 mutex_lock(&opts->lock);
1203 if (fmt->linked || opts->refcnt) {
1208 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n);
1212 tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL);
1218 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp);
1224 kfree(ch->dw_frame_interval);
1225 ch->dw_frame_interval = frm_intrv;
1226 ch->frame.b_frame_interval_type = n;
1227 sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
1228 uvcg_config_compare_u32, NULL);
1232 mutex_unlock(&opts->lock);
1233 mutex_unlock(su_mutex);
1237 UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
1239 static struct configfs_attribute *uvcg_frame_attrs[] = {
1240 &uvcg_frame_attr_b_frame_index,
1241 &uvcg_frame_attr_bm_capabilities,
1242 &uvcg_frame_attr_w_width,
1243 &uvcg_frame_attr_w_height,
1244 &uvcg_frame_attr_dw_min_bit_rate,
1245 &uvcg_frame_attr_dw_max_bit_rate,
1246 &uvcg_frame_attr_dw_max_video_frame_buffer_size,
1247 &uvcg_frame_attr_dw_default_frame_interval,
1248 &uvcg_frame_attr_dw_frame_interval,
1252 static const struct config_item_type uvcg_frame_type = {
1253 .ct_item_ops = &uvcg_config_item_ops,
1254 .ct_attrs = uvcg_frame_attrs,
1255 .ct_owner = THIS_MODULE,
1258 static struct config_item *uvcg_frame_make(struct config_group *group,
1261 struct uvcg_frame *h;
1262 struct uvcg_format *fmt;
1263 struct f_uvc_opts *opts;
1264 struct config_item *opts_item;
1265 struct uvcg_frame_ptr *frame_ptr;
1267 h = kzalloc(sizeof(*h), GFP_KERNEL);
1269 return ERR_PTR(-ENOMEM);
1271 h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
1272 h->frame.b_frame_index = 1;
1273 h->frame.w_width = 640;
1274 h->frame.w_height = 360;
1275 h->frame.dw_min_bit_rate = 18432000;
1276 h->frame.dw_max_bit_rate = 55296000;
1277 h->frame.dw_max_video_frame_buffer_size = 460800;
1278 h->frame.dw_default_frame_interval = 666666;
1280 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1281 opts = to_f_uvc_opts(opts_item);
1283 mutex_lock(&opts->lock);
1284 fmt = to_uvcg_format(&group->cg_item);
1285 if (fmt->type == UVCG_UNCOMPRESSED) {
1286 h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED;
1287 h->fmt_type = UVCG_UNCOMPRESSED;
1288 } else if (fmt->type == UVCG_MJPEG) {
1289 h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
1290 h->fmt_type = UVCG_MJPEG;
1292 mutex_unlock(&opts->lock);
1294 return ERR_PTR(-EINVAL);
1297 frame_ptr = kzalloc(sizeof(*frame_ptr), GFP_KERNEL);
1299 mutex_unlock(&opts->lock);
1301 return ERR_PTR(-ENOMEM);
1305 list_add_tail(&frame_ptr->entry, &fmt->frames);
1307 mutex_unlock(&opts->lock);
1309 config_item_init_type_name(&h->item, name, &uvcg_frame_type);
1314 static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
1316 struct uvcg_format *fmt;
1317 struct f_uvc_opts *opts;
1318 struct config_item *opts_item;
1319 struct uvcg_frame *target_frm = NULL;
1320 struct uvcg_frame_ptr *frame_ptr, *tmp;
1322 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1323 opts = to_f_uvc_opts(opts_item);
1325 mutex_lock(&opts->lock);
1326 target_frm = container_of(item, struct uvcg_frame, item);
1327 fmt = to_uvcg_format(&group->cg_item);
1329 list_for_each_entry_safe(frame_ptr, tmp, &fmt->frames, entry)
1330 if (frame_ptr->frm == target_frm) {
1331 list_del(&frame_ptr->entry);
1336 mutex_unlock(&opts->lock);
1338 config_item_put(item);
1341 static void uvcg_format_set_indices(struct config_group *fmt)
1343 struct config_item *ci;
1346 list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
1347 struct uvcg_frame *frm;
1349 if (ci->ci_type != &uvcg_frame_type)
1352 frm = to_uvcg_frame(ci);
1353 frm->frame.b_frame_index = i++;
1357 /* -----------------------------------------------------------------------------
1358 * streaming/uncompressed/<NAME>
1361 static struct configfs_group_operations uvcg_uncompressed_group_ops = {
1362 .make_item = uvcg_frame_make,
1363 .drop_item = uvcg_frame_drop,
1366 static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
1369 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1370 struct f_uvc_opts *opts;
1371 struct config_item *opts_item;
1372 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1374 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1376 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1377 opts = to_f_uvc_opts(opts_item);
1379 mutex_lock(&opts->lock);
1380 memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
1381 mutex_unlock(&opts->lock);
1383 mutex_unlock(su_mutex);
1385 return sizeof(ch->desc.guidFormat);
1388 static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
1389 const char *page, size_t len)
1391 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1392 struct f_uvc_opts *opts;
1393 struct config_item *opts_item;
1394 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1397 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1399 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1400 opts = to_f_uvc_opts(opts_item);
1402 mutex_lock(&opts->lock);
1403 if (ch->fmt.linked || opts->refcnt) {
1408 memcpy(ch->desc.guidFormat, page,
1409 min(sizeof(ch->desc.guidFormat), len));
1410 ret = sizeof(ch->desc.guidFormat);
1413 mutex_unlock(&opts->lock);
1414 mutex_unlock(su_mutex);
1418 UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
1420 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, bits) \
1421 static ssize_t uvcg_uncompressed_##cname##_show( \
1422 struct config_item *item, char *page) \
1424 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1425 struct f_uvc_opts *opts; \
1426 struct config_item *opts_item; \
1427 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1430 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1432 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1433 opts = to_f_uvc_opts(opts_item); \
1435 mutex_lock(&opts->lock); \
1436 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1437 mutex_unlock(&opts->lock); \
1439 mutex_unlock(su_mutex); \
1443 UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
1445 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, bits) \
1446 static ssize_t uvcg_uncompressed_##cname##_show( \
1447 struct config_item *item, char *page) \
1449 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1450 struct f_uvc_opts *opts; \
1451 struct config_item *opts_item; \
1452 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1455 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1457 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1458 opts = to_f_uvc_opts(opts_item); \
1460 mutex_lock(&opts->lock); \
1461 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1462 mutex_unlock(&opts->lock); \
1464 mutex_unlock(su_mutex); \
1469 uvcg_uncompressed_##cname##_store(struct config_item *item, \
1470 const char *page, size_t len) \
1472 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1473 struct f_uvc_opts *opts; \
1474 struct config_item *opts_item; \
1475 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1479 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1481 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1482 opts = to_f_uvc_opts(opts_item); \
1484 mutex_lock(&opts->lock); \
1485 if (u->fmt.linked || opts->refcnt) { \
1490 ret = kstrtou8(page, 0, &num); \
1494 /* index values in uvc are never 0 */ \
1500 u->desc.aname = num; \
1503 mutex_unlock(&opts->lock); \
1504 mutex_unlock(su_mutex); \
1508 UVC_ATTR(uvcg_uncompressed_, cname, aname);
1510 UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, 8);
1511 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8);
1512 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
1513 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
1514 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
1515 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
1517 #undef UVCG_UNCOMPRESSED_ATTR
1518 #undef UVCG_UNCOMPRESSED_ATTR_RO
1520 static inline ssize_t
1521 uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
1523 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1524 return uvcg_format_bma_controls_show(&unc->fmt, page);
1527 static inline ssize_t
1528 uvcg_uncompressed_bma_controls_store(struct config_item *item,
1529 const char *page, size_t len)
1531 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1532 return uvcg_format_bma_controls_store(&unc->fmt, page, len);
1535 UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
1537 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
1538 &uvcg_uncompressed_attr_b_format_index,
1539 &uvcg_uncompressed_attr_guid_format,
1540 &uvcg_uncompressed_attr_b_bits_per_pixel,
1541 &uvcg_uncompressed_attr_b_default_frame_index,
1542 &uvcg_uncompressed_attr_b_aspect_ratio_x,
1543 &uvcg_uncompressed_attr_b_aspect_ratio_y,
1544 &uvcg_uncompressed_attr_bm_interface_flags,
1545 &uvcg_uncompressed_attr_bma_controls,
1549 static const struct config_item_type uvcg_uncompressed_type = {
1550 .ct_item_ops = &uvcg_config_item_ops,
1551 .ct_group_ops = &uvcg_uncompressed_group_ops,
1552 .ct_attrs = uvcg_uncompressed_attrs,
1553 .ct_owner = THIS_MODULE,
1556 static struct config_group *uvcg_uncompressed_make(struct config_group *group,
1559 static char guid[] = {
1560 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
1561 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1563 struct uvcg_uncompressed *h;
1565 h = kzalloc(sizeof(*h), GFP_KERNEL);
1567 return ERR_PTR(-ENOMEM);
1569 h->desc.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE;
1570 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1571 h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED;
1572 memcpy(h->desc.guidFormat, guid, sizeof(guid));
1573 h->desc.bBitsPerPixel = 16;
1574 h->desc.bDefaultFrameIndex = 1;
1575 h->desc.bAspectRatioX = 0;
1576 h->desc.bAspectRatioY = 0;
1577 h->desc.bmInterfaceFlags = 0;
1578 h->desc.bCopyProtect = 0;
1580 INIT_LIST_HEAD(&h->fmt.frames);
1581 h->fmt.type = UVCG_UNCOMPRESSED;
1582 config_group_init_type_name(&h->fmt.group, name,
1583 &uvcg_uncompressed_type);
1585 return &h->fmt.group;
1588 static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
1589 .make_group = uvcg_uncompressed_make,
1592 static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = {
1594 .ct_item_ops = &uvcg_config_item_ops,
1595 .ct_group_ops = &uvcg_uncompressed_grp_ops,
1596 .ct_owner = THIS_MODULE,
1598 .name = "uncompressed",
1601 /* -----------------------------------------------------------------------------
1602 * streaming/mjpeg/<NAME>
1605 static struct configfs_group_operations uvcg_mjpeg_group_ops = {
1606 .make_item = uvcg_frame_make,
1607 .drop_item = uvcg_frame_drop,
1610 #define UVCG_MJPEG_ATTR_RO(cname, aname, bits) \
1611 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1613 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1614 struct f_uvc_opts *opts; \
1615 struct config_item *opts_item; \
1616 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1619 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1621 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1622 opts = to_f_uvc_opts(opts_item); \
1624 mutex_lock(&opts->lock); \
1625 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1626 mutex_unlock(&opts->lock); \
1628 mutex_unlock(su_mutex); \
1632 UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
1634 #define UVCG_MJPEG_ATTR(cname, aname, bits) \
1635 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1637 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1638 struct f_uvc_opts *opts; \
1639 struct config_item *opts_item; \
1640 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1643 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1645 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1646 opts = to_f_uvc_opts(opts_item); \
1648 mutex_lock(&opts->lock); \
1649 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1650 mutex_unlock(&opts->lock); \
1652 mutex_unlock(su_mutex); \
1657 uvcg_mjpeg_##cname##_store(struct config_item *item, \
1658 const char *page, size_t len) \
1660 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1661 struct f_uvc_opts *opts; \
1662 struct config_item *opts_item; \
1663 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1667 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1669 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1670 opts = to_f_uvc_opts(opts_item); \
1672 mutex_lock(&opts->lock); \
1673 if (u->fmt.linked || opts->refcnt) { \
1678 ret = kstrtou8(page, 0, &num); \
1682 /* index values in uvc are never 0 */ \
1688 u->desc.aname = num; \
1691 mutex_unlock(&opts->lock); \
1692 mutex_unlock(su_mutex); \
1696 UVC_ATTR(uvcg_mjpeg_, cname, aname)
1698 UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, 8);
1699 UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
1700 UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8);
1701 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
1702 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
1703 UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
1705 #undef UVCG_MJPEG_ATTR
1706 #undef UVCG_MJPEG_ATTR_RO
1708 static inline ssize_t
1709 uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
1711 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1712 return uvcg_format_bma_controls_show(&u->fmt, page);
1715 static inline ssize_t
1716 uvcg_mjpeg_bma_controls_store(struct config_item *item,
1717 const char *page, size_t len)
1719 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1720 return uvcg_format_bma_controls_store(&u->fmt, page, len);
1723 UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
1725 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
1726 &uvcg_mjpeg_attr_b_format_index,
1727 &uvcg_mjpeg_attr_b_default_frame_index,
1728 &uvcg_mjpeg_attr_bm_flags,
1729 &uvcg_mjpeg_attr_b_aspect_ratio_x,
1730 &uvcg_mjpeg_attr_b_aspect_ratio_y,
1731 &uvcg_mjpeg_attr_bm_interface_flags,
1732 &uvcg_mjpeg_attr_bma_controls,
1736 static const struct config_item_type uvcg_mjpeg_type = {
1737 .ct_item_ops = &uvcg_config_item_ops,
1738 .ct_group_ops = &uvcg_mjpeg_group_ops,
1739 .ct_attrs = uvcg_mjpeg_attrs,
1740 .ct_owner = THIS_MODULE,
1743 static struct config_group *uvcg_mjpeg_make(struct config_group *group,
1746 struct uvcg_mjpeg *h;
1748 h = kzalloc(sizeof(*h), GFP_KERNEL);
1750 return ERR_PTR(-ENOMEM);
1752 h->desc.bLength = UVC_DT_FORMAT_MJPEG_SIZE;
1753 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1754 h->desc.bDescriptorSubType = UVC_VS_FORMAT_MJPEG;
1755 h->desc.bDefaultFrameIndex = 1;
1756 h->desc.bAspectRatioX = 0;
1757 h->desc.bAspectRatioY = 0;
1758 h->desc.bmInterfaceFlags = 0;
1759 h->desc.bCopyProtect = 0;
1761 INIT_LIST_HEAD(&h->fmt.frames);
1762 h->fmt.type = UVCG_MJPEG;
1763 config_group_init_type_name(&h->fmt.group, name,
1766 return &h->fmt.group;
1769 static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
1770 .make_group = uvcg_mjpeg_make,
1773 static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
1775 .ct_item_ops = &uvcg_config_item_ops,
1776 .ct_group_ops = &uvcg_mjpeg_grp_ops,
1777 .ct_owner = THIS_MODULE,
1782 /* -----------------------------------------------------------------------------
1783 * streaming/color_matching/default
1786 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, bits) \
1787 static ssize_t uvcg_default_color_matching_##cname##_show( \
1788 struct config_item *item, char *page) \
1790 struct config_group *group = to_config_group(item); \
1791 struct f_uvc_opts *opts; \
1792 struct config_item *opts_item; \
1793 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
1794 struct uvc_color_matching_descriptor *cd; \
1797 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1799 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
1800 opts = to_f_uvc_opts(opts_item); \
1801 cd = &opts->uvc_color_matching; \
1803 mutex_lock(&opts->lock); \
1804 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
1805 mutex_unlock(&opts->lock); \
1807 mutex_unlock(su_mutex); \
1811 UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
1813 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 8);
1814 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics,
1815 bTransferCharacteristics, 8);
1816 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 8);
1818 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1820 static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
1821 &uvcg_default_color_matching_attr_b_color_primaries,
1822 &uvcg_default_color_matching_attr_b_transfer_characteristics,
1823 &uvcg_default_color_matching_attr_b_matrix_coefficients,
1827 static const struct uvcg_config_group_type uvcg_default_color_matching_type = {
1829 .ct_item_ops = &uvcg_config_item_ops,
1830 .ct_attrs = uvcg_default_color_matching_attrs,
1831 .ct_owner = THIS_MODULE,
1836 /* -----------------------------------------------------------------------------
1837 * streaming/color_matching
1840 static const struct uvcg_config_group_type uvcg_color_matching_grp_type = {
1842 .ct_item_ops = &uvcg_config_item_ops,
1843 .ct_owner = THIS_MODULE,
1845 .name = "color_matching",
1846 .children = (const struct uvcg_config_group_type*[]) {
1847 &uvcg_default_color_matching_type,
1852 /* -----------------------------------------------------------------------------
1853 * streaming/class/{fs|hs|ss}
1856 struct uvcg_streaming_class_group {
1857 struct config_group group;
1861 static inline struct uvc_descriptor_header
1862 ***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
1864 struct uvcg_streaming_class_group *group =
1865 container_of(i, struct uvcg_streaming_class_group,
1868 if (!strcmp(group->name, "fs"))
1869 return &o->uvc_fs_streaming_cls;
1871 if (!strcmp(group->name, "hs"))
1872 return &o->uvc_hs_streaming_cls;
1874 if (!strcmp(group->name, "ss"))
1875 return &o->uvc_ss_streaming_cls;
1880 enum uvcg_strm_type {
1887 * Iterate over a hierarchy of streaming descriptors' config items.
1888 * The items are created by the user with configfs.
1890 * It "processes" the header pointed to by @priv1, then for each format
1891 * that follows the header "processes" the format itself and then for
1892 * each frame inside a format "processes" the frame.
1894 * As a "processing" function the @fun is used.
1896 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
1897 * the amount of memory needed for an array of streaming descriptors
1898 * and second, to actually fill the array.
1900 * @h: streaming header pointer
1901 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
1902 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
1903 * @fun: callback function for processing each level of the hierarchy
1905 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
1906 void *priv2, void *priv3,
1907 int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type))
1909 struct uvcg_format_ptr *f;
1910 struct config_group *grp;
1911 struct config_item *item;
1912 struct uvcg_frame *frm;
1919 ret = fun(h, priv2, priv3, 0, UVCG_HEADER);
1922 list_for_each_entry(f, &h->formats, entry) {
1923 ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT);
1926 grp = &f->fmt->group;
1927 list_for_each_entry(item, &grp->cg_children, ci_entry) {
1928 frm = to_uvcg_frame(item);
1929 ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
1939 * Count how many bytes are needed for an array of streaming descriptors.
1941 * @priv1: pointer to a header, format or frame
1942 * @priv2: inout parameter, accumulated size of the array
1943 * @priv3: inout parameter, accumulated number of the array elements
1944 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
1946 static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
1947 enum uvcg_strm_type type)
1949 size_t *size = priv2;
1950 size_t *count = priv3;
1954 struct uvcg_streaming_header *h = priv1;
1956 *size += sizeof(h->desc);
1958 *size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE;
1962 struct uvcg_format *fmt = priv1;
1964 if (fmt->type == UVCG_UNCOMPRESSED) {
1965 struct uvcg_uncompressed *u =
1966 container_of(fmt, struct uvcg_uncompressed,
1969 *size += sizeof(u->desc);
1970 } else if (fmt->type == UVCG_MJPEG) {
1971 struct uvcg_mjpeg *m =
1972 container_of(fmt, struct uvcg_mjpeg, fmt);
1974 *size += sizeof(m->desc);
1981 struct uvcg_frame *frm = priv1;
1982 int sz = sizeof(frm->dw_frame_interval);
1984 *size += sizeof(frm->frame);
1985 *size += frm->frame.b_frame_interval_type * sz;
1996 * Fill an array of streaming descriptors.
1998 * @priv1: pointer to a header, format or frame
1999 * @priv2: inout parameter, pointer into a block of memory
2000 * @priv3: inout parameter, pointer to a 2-dimensional array
2002 static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
2003 enum uvcg_strm_type type)
2005 void **dest = priv2;
2006 struct uvc_descriptor_header ***array = priv3;
2014 struct uvc_input_header_descriptor *ihdr = *dest;
2015 struct uvcg_streaming_header *h = priv1;
2016 struct uvcg_format_ptr *f;
2018 memcpy(*dest, &h->desc, sizeof(h->desc));
2019 *dest += sizeof(h->desc);
2020 sz = UVCG_STREAMING_CONTROL_SIZE;
2021 list_for_each_entry(f, &h->formats, entry) {
2022 memcpy(*dest, f->fmt->bmaControls, sz);
2025 ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz;
2026 ihdr->bNumFormats = h->num_fmt;
2030 struct uvcg_format *fmt = priv1;
2032 if (fmt->type == UVCG_UNCOMPRESSED) {
2033 struct uvcg_uncompressed *u =
2034 container_of(fmt, struct uvcg_uncompressed,
2037 u->desc.bFormatIndex = n + 1;
2038 u->desc.bNumFrameDescriptors = fmt->num_frames;
2039 memcpy(*dest, &u->desc, sizeof(u->desc));
2040 *dest += sizeof(u->desc);
2041 } else if (fmt->type == UVCG_MJPEG) {
2042 struct uvcg_mjpeg *m =
2043 container_of(fmt, struct uvcg_mjpeg, fmt);
2045 m->desc.bFormatIndex = n + 1;
2046 m->desc.bNumFrameDescriptors = fmt->num_frames;
2047 memcpy(*dest, &m->desc, sizeof(m->desc));
2048 *dest += sizeof(m->desc);
2055 struct uvcg_frame *frm = priv1;
2056 struct uvc_descriptor_header *h = *dest;
2058 sz = sizeof(frm->frame);
2059 memcpy(*dest, &frm->frame, sz);
2061 sz = frm->frame.b_frame_interval_type *
2062 sizeof(*frm->dw_frame_interval);
2063 memcpy(*dest, frm->dw_frame_interval, sz);
2065 if (frm->fmt_type == UVCG_UNCOMPRESSED)
2066 h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
2067 frm->frame.b_frame_interval_type);
2068 else if (frm->fmt_type == UVCG_MJPEG)
2069 h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
2070 frm->frame.b_frame_interval_type);
2078 static int uvcg_streaming_class_allow_link(struct config_item *src,
2079 struct config_item *target)
2081 struct config_item *streaming, *header;
2082 struct f_uvc_opts *opts;
2083 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2084 struct uvc_descriptor_header ***class_array, **cl_arr;
2085 struct uvcg_streaming_header *target_hdr;
2086 void *data, *data_save;
2087 size_t size = 0, count = 0;
2090 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2092 streaming = src->ci_parent->ci_parent;
2093 header = config_group_find_item(to_config_group(streaming), "header");
2094 if (!header || target->ci_parent != header)
2097 opts = to_f_uvc_opts(streaming->ci_parent);
2099 mutex_lock(&opts->lock);
2101 class_array = __uvcg_get_stream_class_arr(src, opts);
2102 if (!class_array || *class_array || opts->refcnt) {
2107 target_hdr = to_uvcg_streaming_header(target);
2108 ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm);
2112 count += 2; /* color_matching, NULL */
2113 *class_array = kcalloc(count, sizeof(void *), GFP_KERNEL);
2114 if (!*class_array) {
2119 data = data_save = kzalloc(size, GFP_KERNEL);
2121 kfree(*class_array);
2122 *class_array = NULL;
2126 cl_arr = *class_array;
2127 ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr,
2130 kfree(*class_array);
2131 *class_array = NULL;
2133 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2134 * might have advanced the "data", so use a backup copy
2139 *cl_arr = (struct uvc_descriptor_header *)&opts->uvc_color_matching;
2141 ++target_hdr->linked;
2145 mutex_unlock(&opts->lock);
2147 config_item_put(header);
2148 mutex_unlock(su_mutex);
2152 static void uvcg_streaming_class_drop_link(struct config_item *src,
2153 struct config_item *target)
2155 struct config_item *streaming, *header;
2156 struct f_uvc_opts *opts;
2157 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2158 struct uvc_descriptor_header ***class_array;
2159 struct uvcg_streaming_header *target_hdr;
2161 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2163 streaming = src->ci_parent->ci_parent;
2164 header = config_group_find_item(to_config_group(streaming), "header");
2165 if (!header || target->ci_parent != header)
2168 opts = to_f_uvc_opts(streaming->ci_parent);
2170 mutex_lock(&opts->lock);
2172 class_array = __uvcg_get_stream_class_arr(src, opts);
2173 if (!class_array || !*class_array)
2179 target_hdr = to_uvcg_streaming_header(target);
2180 --target_hdr->linked;
2181 kfree(**class_array);
2182 kfree(*class_array);
2183 *class_array = NULL;
2186 mutex_unlock(&opts->lock);
2188 config_item_put(header);
2189 mutex_unlock(su_mutex);
2192 static struct configfs_item_operations uvcg_streaming_class_item_ops = {
2193 .release = uvcg_config_item_release,
2194 .allow_link = uvcg_streaming_class_allow_link,
2195 .drop_link = uvcg_streaming_class_drop_link,
2198 static const struct config_item_type uvcg_streaming_class_type = {
2199 .ct_item_ops = &uvcg_streaming_class_item_ops,
2200 .ct_owner = THIS_MODULE,
2203 /* -----------------------------------------------------------------------------
2207 static int uvcg_streaming_class_create_children(struct config_group *parent)
2209 static const char * const names[] = { "fs", "hs", "ss" };
2212 for (i = 0; i < ARRAY_SIZE(names); ++i) {
2213 struct uvcg_streaming_class_group *group;
2215 group = kzalloc(sizeof(*group), GFP_KERNEL);
2219 group->name = names[i];
2221 config_group_init_type_name(&group->group, group->name,
2222 &uvcg_streaming_class_type);
2223 configfs_add_default_group(&group->group, parent);
2229 static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = {
2231 .ct_item_ops = &uvcg_config_item_ops,
2232 .ct_owner = THIS_MODULE,
2235 .create_children = uvcg_streaming_class_create_children,
2238 /* -----------------------------------------------------------------------------
2242 static ssize_t uvcg_default_streaming_b_interface_number_show(
2243 struct config_item *item, char *page)
2245 struct config_group *group = to_config_group(item);
2246 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
2247 struct config_item *opts_item;
2248 struct f_uvc_opts *opts;
2251 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2253 opts_item = item->ci_parent;
2254 opts = to_f_uvc_opts(opts_item);
2256 mutex_lock(&opts->lock);
2257 result += sprintf(page, "%u\n", opts->streaming_interface);
2258 mutex_unlock(&opts->lock);
2260 mutex_unlock(su_mutex);
2265 UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber);
2267 static struct configfs_attribute *uvcg_default_streaming_attrs[] = {
2268 &uvcg_default_streaming_attr_b_interface_number,
2272 static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
2274 .ct_item_ops = &uvcg_config_item_ops,
2275 .ct_attrs = uvcg_default_streaming_attrs,
2276 .ct_owner = THIS_MODULE,
2278 .name = "streaming",
2279 .children = (const struct uvcg_config_group_type*[]) {
2280 &uvcg_streaming_header_grp_type,
2281 &uvcg_uncompressed_grp_type,
2282 &uvcg_mjpeg_grp_type,
2283 &uvcg_color_matching_grp_type,
2284 &uvcg_streaming_class_grp_type,
2289 /* -----------------------------------------------------------------------------
2293 static void uvc_func_item_release(struct config_item *item)
2295 struct f_uvc_opts *opts = to_f_uvc_opts(item);
2297 uvcg_config_remove_children(to_config_group(item));
2298 usb_put_function_instance(&opts->func_inst);
2301 static struct configfs_item_operations uvc_func_item_ops = {
2302 .release = uvc_func_item_release,
2305 #define UVCG_OPTS_ATTR(cname, aname, limit) \
2306 static ssize_t f_uvc_opts_##cname##_show( \
2307 struct config_item *item, char *page) \
2309 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2312 mutex_lock(&opts->lock); \
2313 result = sprintf(page, "%u\n", opts->cname); \
2314 mutex_unlock(&opts->lock); \
2320 f_uvc_opts_##cname##_store(struct config_item *item, \
2321 const char *page, size_t len) \
2323 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2327 mutex_lock(&opts->lock); \
2328 if (opts->refcnt) { \
2333 ret = kstrtouint(page, 0, &num); \
2337 if (num > limit) { \
2341 opts->cname = num; \
2344 mutex_unlock(&opts->lock); \
2348 UVC_ATTR(f_uvc_opts_, cname, cname)
2350 UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16);
2351 UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072);
2352 UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15);
2354 #undef UVCG_OPTS_ATTR
2356 #define UVCG_OPTS_STRING_ATTR(cname, aname) \
2357 static ssize_t f_uvc_opts_string_##cname##_show(struct config_item *item,\
2360 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2363 mutex_lock(&opts->lock); \
2364 result = snprintf(page, sizeof(opts->aname), "%s", opts->aname);\
2365 mutex_unlock(&opts->lock); \
2370 static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\
2371 const char *page, size_t len) \
2373 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2376 mutex_lock(&opts->lock); \
2377 if (opts->refcnt) { \
2382 ret = snprintf(opts->aname, min(sizeof(opts->aname), len), \
2386 mutex_unlock(&opts->lock); \
2390 UVC_ATTR(f_uvc_opts_string_, cname, aname)
2392 UVCG_OPTS_STRING_ATTR(function_name, function_name);
2394 #undef UVCG_OPTS_STRING_ATTR
2396 static struct configfs_attribute *uvc_attrs[] = {
2397 &f_uvc_opts_attr_streaming_interval,
2398 &f_uvc_opts_attr_streaming_maxpacket,
2399 &f_uvc_opts_attr_streaming_maxburst,
2400 &f_uvc_opts_string_attr_function_name,
2404 static const struct uvcg_config_group_type uvc_func_type = {
2406 .ct_item_ops = &uvc_func_item_ops,
2407 .ct_attrs = uvc_attrs,
2408 .ct_owner = THIS_MODULE,
2411 .children = (const struct uvcg_config_group_type*[]) {
2412 &uvcg_control_grp_type,
2413 &uvcg_streaming_grp_type,
2418 int uvcg_attach_configfs(struct f_uvc_opts *opts)
2422 config_group_init_type_name(&opts->func_inst.group, uvc_func_type.name,
2423 &uvc_func_type.type);
2425 ret = uvcg_config_create_children(&opts->func_inst.group,
2428 config_group_put(&opts->func_inst.group);