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 "uvc_configfs.h"
15 #define UVCG_STREAMING_CONTROL_SIZE 1
17 #define UVC_ATTR(prefix, cname, aname) \
18 static struct configfs_attribute prefix##attr_##cname = { \
19 .ca_name = __stringify(aname), \
20 .ca_mode = S_IRUGO | S_IWUGO, \
21 .ca_owner = THIS_MODULE, \
22 .show = prefix##cname##_show, \
23 .store = prefix##cname##_store, \
26 #define UVC_ATTR_RO(prefix, cname, aname) \
27 static struct configfs_attribute prefix##attr_##cname = { \
28 .ca_name = __stringify(aname), \
30 .ca_owner = THIS_MODULE, \
31 .show = prefix##cname##_show, \
34 static inline struct f_uvc_opts
*to_f_uvc_opts(struct config_item
*item
);
36 /* control/header/<NAME> */
37 DECLARE_UVC_HEADER_DESCRIPTOR(1);
39 struct uvcg_control_header
{
40 struct config_item item
;
41 struct UVC_HEADER_DESCRIPTOR(1) desc
;
45 static struct uvcg_control_header
*to_uvcg_control_header(struct config_item
*item
)
47 return container_of(item
, struct uvcg_control_header
, item
);
50 #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
51 static ssize_t uvcg_control_header_##cname##_show( \
52 struct config_item *item, char *page) \
54 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
55 struct f_uvc_opts *opts; \
56 struct config_item *opts_item; \
57 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
60 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
62 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
63 opts = to_f_uvc_opts(opts_item); \
65 mutex_lock(&opts->lock); \
66 result = sprintf(page, "%d\n", conv(ch->desc.aname)); \
67 mutex_unlock(&opts->lock); \
69 mutex_unlock(su_mutex); \
74 uvcg_control_header_##cname##_store(struct config_item *item, \
75 const char *page, size_t len) \
77 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
78 struct f_uvc_opts *opts; \
79 struct config_item *opts_item; \
80 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
84 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
86 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
87 opts = to_f_uvc_opts(opts_item); \
89 mutex_lock(&opts->lock); \
90 if (ch->linked || opts->refcnt) { \
95 ret = str2u(page, 0, &num); \
103 ch->desc.aname = vnoc(num); \
106 mutex_unlock(&opts->lock); \
107 mutex_unlock(su_mutex); \
111 UVC_ATTR(uvcg_control_header_, cname, aname)
113 UVCG_CTRL_HDR_ATTR(bcd_uvc
, bcdUVC
, le16_to_cpu
, kstrtou16
, u16
, cpu_to_le16
,
116 UVCG_CTRL_HDR_ATTR(dw_clock_frequency
, dwClockFrequency
, le32_to_cpu
, kstrtou32
,
117 u32
, cpu_to_le32
, 0x7fffffff);
119 #undef UVCG_CTRL_HDR_ATTR
121 static struct configfs_attribute
*uvcg_control_header_attrs
[] = {
122 &uvcg_control_header_attr_bcd_uvc
,
123 &uvcg_control_header_attr_dw_clock_frequency
,
127 static const struct config_item_type uvcg_control_header_type
= {
128 .ct_attrs
= uvcg_control_header_attrs
,
129 .ct_owner
= THIS_MODULE
,
132 static struct config_item
*uvcg_control_header_make(struct config_group
*group
,
135 struct uvcg_control_header
*h
;
137 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
139 return ERR_PTR(-ENOMEM
);
141 h
->desc
.bLength
= UVC_DT_HEADER_SIZE(1);
142 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
143 h
->desc
.bDescriptorSubType
= UVC_VC_HEADER
;
144 h
->desc
.bcdUVC
= cpu_to_le16(0x0100);
145 h
->desc
.dwClockFrequency
= cpu_to_le32(48000000);
147 config_item_init_type_name(&h
->item
, name
, &uvcg_control_header_type
);
152 static void uvcg_control_header_drop(struct config_group
*group
,
153 struct config_item
*item
)
155 struct uvcg_control_header
*h
= to_uvcg_control_header(item
);
161 static struct uvcg_control_header_grp
{
162 struct config_group group
;
163 } uvcg_control_header_grp
;
165 static struct configfs_group_operations uvcg_control_header_grp_ops
= {
166 .make_item
= uvcg_control_header_make
,
167 .drop_item
= uvcg_control_header_drop
,
170 static const struct config_item_type uvcg_control_header_grp_type
= {
171 .ct_group_ops
= &uvcg_control_header_grp_ops
,
172 .ct_owner
= THIS_MODULE
,
175 /* control/processing/default */
176 static struct uvcg_default_processing
{
177 struct config_group group
;
178 } uvcg_default_processing
;
180 static inline struct uvcg_default_processing
181 *to_uvcg_default_processing(struct config_item
*item
)
183 return container_of(to_config_group(item
),
184 struct uvcg_default_processing
, group
);
187 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
188 static ssize_t uvcg_default_processing_##cname##_show( \
189 struct config_item *item, char *page) \
191 struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
192 struct f_uvc_opts *opts; \
193 struct config_item *opts_item; \
194 struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
195 struct uvc_processing_unit_descriptor *pd; \
198 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
200 opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \
201 opts = to_f_uvc_opts(opts_item); \
202 pd = &opts->uvc_processing; \
204 mutex_lock(&opts->lock); \
205 result = sprintf(page, "%d\n", conv(pd->aname)); \
206 mutex_unlock(&opts->lock); \
208 mutex_unlock(su_mutex); \
212 UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
214 #define identity_conv(x) (x)
216 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id
, bUnitID
, identity_conv
);
217 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id
, bSourceID
, identity_conv
);
218 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier
, wMaxMultiplier
, le16_to_cpu
);
219 UVCG_DEFAULT_PROCESSING_ATTR(i_processing
, iProcessing
, identity_conv
);
223 #undef UVCG_DEFAULT_PROCESSING_ATTR
225 static ssize_t
uvcg_default_processing_bm_controls_show(
226 struct config_item
*item
, char *page
)
228 struct uvcg_default_processing
*dp
= to_uvcg_default_processing(item
);
229 struct f_uvc_opts
*opts
;
230 struct config_item
*opts_item
;
231 struct mutex
*su_mutex
= &dp
->group
.cg_subsys
->su_mutex
;
232 struct uvc_processing_unit_descriptor
*pd
;
236 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
238 opts_item
= dp
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
239 opts
= to_f_uvc_opts(opts_item
);
240 pd
= &opts
->uvc_processing
;
242 mutex_lock(&opts
->lock
);
243 for (result
= 0, i
= 0; i
< pd
->bControlSize
; ++i
) {
244 result
+= sprintf(pg
, "%d\n", pd
->bmControls
[i
]);
247 mutex_unlock(&opts
->lock
);
249 mutex_unlock(su_mutex
);
254 UVC_ATTR_RO(uvcg_default_processing_
, bm_controls
, bmControls
);
256 static struct configfs_attribute
*uvcg_default_processing_attrs
[] = {
257 &uvcg_default_processing_attr_b_unit_id
,
258 &uvcg_default_processing_attr_b_source_id
,
259 &uvcg_default_processing_attr_w_max_multiplier
,
260 &uvcg_default_processing_attr_bm_controls
,
261 &uvcg_default_processing_attr_i_processing
,
265 static const struct config_item_type uvcg_default_processing_type
= {
266 .ct_attrs
= uvcg_default_processing_attrs
,
267 .ct_owner
= THIS_MODULE
,
270 /* struct uvcg_processing {}; */
272 /* control/processing */
273 static struct uvcg_processing_grp
{
274 struct config_group group
;
275 } uvcg_processing_grp
;
277 static const struct config_item_type uvcg_processing_grp_type
= {
278 .ct_owner
= THIS_MODULE
,
281 /* control/terminal/camera/default */
282 static struct uvcg_default_camera
{
283 struct config_group group
;
284 } uvcg_default_camera
;
286 static inline struct uvcg_default_camera
287 *to_uvcg_default_camera(struct config_item
*item
)
289 return container_of(to_config_group(item
),
290 struct uvcg_default_camera
, group
);
293 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
294 static ssize_t uvcg_default_camera_##cname##_show( \
295 struct config_item *item, char *page) \
297 struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \
298 struct f_uvc_opts *opts; \
299 struct config_item *opts_item; \
300 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
301 struct uvc_camera_terminal_descriptor *cd; \
304 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
306 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> \
308 opts = to_f_uvc_opts(opts_item); \
309 cd = &opts->uvc_camera_terminal; \
311 mutex_lock(&opts->lock); \
312 result = sprintf(page, "%d\n", conv(cd->aname)); \
313 mutex_unlock(&opts->lock); \
315 mutex_unlock(su_mutex); \
320 UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
322 #define identity_conv(x) (x)
324 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id
, bTerminalID
, identity_conv
);
325 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type
, wTerminalType
, le16_to_cpu
);
326 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal
, bAssocTerminal
, identity_conv
);
327 UVCG_DEFAULT_CAMERA_ATTR(i_terminal
, iTerminal
, identity_conv
);
328 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min
, wObjectiveFocalLengthMin
,
330 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max
, wObjectiveFocalLengthMax
,
332 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length
, wOcularFocalLength
,
337 #undef UVCG_DEFAULT_CAMERA_ATTR
339 static ssize_t
uvcg_default_camera_bm_controls_show(
340 struct config_item
*item
, char *page
)
342 struct uvcg_default_camera
*dc
= to_uvcg_default_camera(item
);
343 struct f_uvc_opts
*opts
;
344 struct config_item
*opts_item
;
345 struct mutex
*su_mutex
= &dc
->group
.cg_subsys
->su_mutex
;
346 struct uvc_camera_terminal_descriptor
*cd
;
350 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
352 opts_item
= dc
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
->
354 opts
= to_f_uvc_opts(opts_item
);
355 cd
= &opts
->uvc_camera_terminal
;
357 mutex_lock(&opts
->lock
);
358 for (result
= 0, i
= 0; i
< cd
->bControlSize
; ++i
) {
359 result
+= sprintf(pg
, "%d\n", cd
->bmControls
[i
]);
362 mutex_unlock(&opts
->lock
);
364 mutex_unlock(su_mutex
);
368 UVC_ATTR_RO(uvcg_default_camera_
, bm_controls
, bmControls
);
370 static struct configfs_attribute
*uvcg_default_camera_attrs
[] = {
371 &uvcg_default_camera_attr_b_terminal_id
,
372 &uvcg_default_camera_attr_w_terminal_type
,
373 &uvcg_default_camera_attr_b_assoc_terminal
,
374 &uvcg_default_camera_attr_i_terminal
,
375 &uvcg_default_camera_attr_w_objective_focal_length_min
,
376 &uvcg_default_camera_attr_w_objective_focal_length_max
,
377 &uvcg_default_camera_attr_w_ocular_focal_length
,
378 &uvcg_default_camera_attr_bm_controls
,
382 static const struct config_item_type uvcg_default_camera_type
= {
383 .ct_attrs
= uvcg_default_camera_attrs
,
384 .ct_owner
= THIS_MODULE
,
387 /* struct uvcg_camera {}; */
389 /* control/terminal/camera */
390 static struct uvcg_camera_grp
{
391 struct config_group group
;
394 static const struct config_item_type uvcg_camera_grp_type
= {
395 .ct_owner
= THIS_MODULE
,
398 /* control/terminal/output/default */
399 static struct uvcg_default_output
{
400 struct config_group group
;
401 } uvcg_default_output
;
403 static inline struct uvcg_default_output
404 *to_uvcg_default_output(struct config_item
*item
)
406 return container_of(to_config_group(item
),
407 struct uvcg_default_output
, group
);
410 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
411 static ssize_t uvcg_default_output_##cname##_show( \
412 struct config_item *item, char *page) \
414 struct uvcg_default_output *dout = to_uvcg_default_output(item); \
415 struct f_uvc_opts *opts; \
416 struct config_item *opts_item; \
417 struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
418 struct uvc_output_terminal_descriptor *cd; \
421 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
423 opts_item = dout->group.cg_item.ci_parent->ci_parent-> \
424 ci_parent->ci_parent; \
425 opts = to_f_uvc_opts(opts_item); \
426 cd = &opts->uvc_output_terminal; \
428 mutex_lock(&opts->lock); \
429 result = sprintf(page, "%d\n", conv(cd->aname)); \
430 mutex_unlock(&opts->lock); \
432 mutex_unlock(su_mutex); \
437 UVC_ATTR_RO(uvcg_default_output_, cname, aname)
439 #define identity_conv(x) (x)
441 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id
, bTerminalID
, identity_conv
);
442 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type
, wTerminalType
, le16_to_cpu
);
443 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal
, bAssocTerminal
, identity_conv
);
444 UVCG_DEFAULT_OUTPUT_ATTR(b_source_id
, bSourceID
, identity_conv
);
445 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal
, iTerminal
, identity_conv
);
449 #undef UVCG_DEFAULT_OUTPUT_ATTR
451 static struct configfs_attribute
*uvcg_default_output_attrs
[] = {
452 &uvcg_default_output_attr_b_terminal_id
,
453 &uvcg_default_output_attr_w_terminal_type
,
454 &uvcg_default_output_attr_b_assoc_terminal
,
455 &uvcg_default_output_attr_b_source_id
,
456 &uvcg_default_output_attr_i_terminal
,
460 static const struct config_item_type uvcg_default_output_type
= {
461 .ct_attrs
= uvcg_default_output_attrs
,
462 .ct_owner
= THIS_MODULE
,
465 /* struct uvcg_output {}; */
467 /* control/terminal/output */
468 static struct uvcg_output_grp
{
469 struct config_group group
;
472 static const struct config_item_type uvcg_output_grp_type
= {
473 .ct_owner
= THIS_MODULE
,
476 /* control/terminal */
477 static struct uvcg_terminal_grp
{
478 struct config_group group
;
481 static const struct config_item_type uvcg_terminal_grp_type
= {
482 .ct_owner
= THIS_MODULE
,
485 /* control/class/{fs} */
486 static struct uvcg_control_class
{
487 struct config_group group
;
488 } uvcg_control_class_fs
, uvcg_control_class_ss
;
491 static inline struct uvc_descriptor_header
492 **uvcg_get_ctl_class_arr(struct config_item
*i
, struct f_uvc_opts
*o
)
494 struct uvcg_control_class
*cl
= container_of(to_config_group(i
),
495 struct uvcg_control_class
, group
);
497 if (cl
== &uvcg_control_class_fs
)
498 return o
->uvc_fs_control_cls
;
500 if (cl
== &uvcg_control_class_ss
)
501 return o
->uvc_ss_control_cls
;
506 static int uvcg_control_class_allow_link(struct config_item
*src
,
507 struct config_item
*target
)
509 struct config_item
*control
, *header
;
510 struct f_uvc_opts
*opts
;
511 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
512 struct uvc_descriptor_header
**class_array
;
513 struct uvcg_control_header
*target_hdr
;
516 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
518 control
= src
->ci_parent
->ci_parent
;
519 header
= config_group_find_item(to_config_group(control
), "header");
520 if (!header
|| target
->ci_parent
!= header
)
523 opts
= to_f_uvc_opts(control
->ci_parent
);
525 mutex_lock(&opts
->lock
);
527 class_array
= uvcg_get_ctl_class_arr(src
, opts
);
530 if (opts
->refcnt
|| class_array
[0]) {
535 target_hdr
= to_uvcg_control_header(target
);
536 ++target_hdr
->linked
;
537 class_array
[0] = (struct uvc_descriptor_header
*)&target_hdr
->desc
;
541 mutex_unlock(&opts
->lock
);
543 mutex_unlock(su_mutex
);
547 static void uvcg_control_class_drop_link(struct config_item
*src
,
548 struct config_item
*target
)
550 struct config_item
*control
, *header
;
551 struct f_uvc_opts
*opts
;
552 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
553 struct uvc_descriptor_header
**class_array
;
554 struct uvcg_control_header
*target_hdr
;
556 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
558 control
= src
->ci_parent
->ci_parent
;
559 header
= config_group_find_item(to_config_group(control
), "header");
560 if (!header
|| target
->ci_parent
!= header
)
563 opts
= to_f_uvc_opts(control
->ci_parent
);
565 mutex_lock(&opts
->lock
);
567 class_array
= uvcg_get_ctl_class_arr(src
, opts
);
568 if (!class_array
|| opts
->refcnt
)
571 target_hdr
= to_uvcg_control_header(target
);
572 --target_hdr
->linked
;
573 class_array
[0] = NULL
;
576 mutex_unlock(&opts
->lock
);
578 mutex_unlock(su_mutex
);
581 static struct configfs_item_operations uvcg_control_class_item_ops
= {
582 .allow_link
= uvcg_control_class_allow_link
,
583 .drop_link
= uvcg_control_class_drop_link
,
586 static const struct config_item_type uvcg_control_class_type
= {
587 .ct_item_ops
= &uvcg_control_class_item_ops
,
588 .ct_owner
= THIS_MODULE
,
592 static struct uvcg_control_class_grp
{
593 struct config_group group
;
594 } uvcg_control_class_grp
;
596 static const struct config_item_type uvcg_control_class_grp_type
= {
597 .ct_owner
= THIS_MODULE
,
601 static struct uvcg_control_grp
{
602 struct config_group group
;
605 static const struct config_item_type uvcg_control_grp_type
= {
606 .ct_owner
= THIS_MODULE
,
609 /* streaming/uncompressed */
610 static struct uvcg_uncompressed_grp
{
611 struct config_group group
;
612 } uvcg_uncompressed_grp
;
614 /* streaming/mjpeg */
615 static struct uvcg_mjpeg_grp
{
616 struct config_group group
;
619 static struct config_item
*fmt_parent
[] = {
620 &uvcg_uncompressed_grp
.group
.cg_item
,
621 &uvcg_mjpeg_grp
.group
.cg_item
,
624 enum uvcg_format_type
{
625 UVCG_UNCOMPRESSED
= 0,
630 struct config_group group
;
631 enum uvcg_format_type type
;
634 __u8 bmaControls
[UVCG_STREAMING_CONTROL_SIZE
];
637 static struct uvcg_format
*to_uvcg_format(struct config_item
*item
)
639 return container_of(to_config_group(item
), struct uvcg_format
, group
);
642 static ssize_t
uvcg_format_bma_controls_show(struct uvcg_format
*f
, char *page
)
644 struct f_uvc_opts
*opts
;
645 struct config_item
*opts_item
;
646 struct mutex
*su_mutex
= &f
->group
.cg_subsys
->su_mutex
;
650 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
652 opts_item
= f
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
653 opts
= to_f_uvc_opts(opts_item
);
655 mutex_lock(&opts
->lock
);
656 result
= sprintf(pg
, "0x");
658 for (i
= 0; i
< UVCG_STREAMING_CONTROL_SIZE
; ++i
) {
659 result
+= sprintf(pg
, "%x\n", f
->bmaControls
[i
]);
662 mutex_unlock(&opts
->lock
);
664 mutex_unlock(su_mutex
);
668 static ssize_t
uvcg_format_bma_controls_store(struct uvcg_format
*ch
,
669 const char *page
, size_t len
)
671 struct f_uvc_opts
*opts
;
672 struct config_item
*opts_item
;
673 struct mutex
*su_mutex
= &ch
->group
.cg_subsys
->su_mutex
;
676 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
678 opts_item
= ch
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
679 opts
= to_f_uvc_opts(opts_item
);
681 mutex_lock(&opts
->lock
);
682 if (ch
->linked
|| opts
->refcnt
) {
687 if (len
< 4 || *page
!= '0' ||
688 (*(page
+ 1) != 'x' && *(page
+ 1) != 'X'))
690 ret
= hex2bin(ch
->bmaControls
, page
+ 2, 1);
695 mutex_unlock(&opts
->lock
);
696 mutex_unlock(su_mutex
);
700 struct uvcg_format_ptr
{
701 struct uvcg_format
*fmt
;
702 struct list_head entry
;
705 /* streaming/header/<NAME> */
706 struct uvcg_streaming_header
{
707 struct config_item item
;
708 struct uvc_input_header_descriptor desc
;
710 struct list_head formats
;
714 static struct uvcg_streaming_header
*to_uvcg_streaming_header(struct config_item
*item
)
716 return container_of(item
, struct uvcg_streaming_header
, item
);
719 static int uvcg_streaming_header_allow_link(struct config_item
*src
,
720 struct config_item
*target
)
722 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
723 struct config_item
*opts_item
;
724 struct f_uvc_opts
*opts
;
725 struct uvcg_streaming_header
*src_hdr
;
726 struct uvcg_format
*target_fmt
= NULL
;
727 struct uvcg_format_ptr
*format_ptr
;
728 int i
, ret
= -EINVAL
;
730 src_hdr
= to_uvcg_streaming_header(src
);
731 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
733 opts_item
= src
->ci_parent
->ci_parent
->ci_parent
;
734 opts
= to_f_uvc_opts(opts_item
);
736 mutex_lock(&opts
->lock
);
738 if (src_hdr
->linked
) {
743 for (i
= 0; i
< ARRAY_SIZE(fmt_parent
); ++i
)
744 if (target
->ci_parent
== fmt_parent
[i
])
746 if (i
== ARRAY_SIZE(fmt_parent
))
749 target_fmt
= container_of(to_config_group(target
), struct uvcg_format
,
754 format_ptr
= kzalloc(sizeof(*format_ptr
), GFP_KERNEL
);
760 format_ptr
->fmt
= target_fmt
;
761 list_add_tail(&format_ptr
->entry
, &src_hdr
->formats
);
765 mutex_unlock(&opts
->lock
);
766 mutex_unlock(su_mutex
);
770 static void uvcg_streaming_header_drop_link(struct config_item
*src
,
771 struct config_item
*target
)
773 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
774 struct config_item
*opts_item
;
775 struct f_uvc_opts
*opts
;
776 struct uvcg_streaming_header
*src_hdr
;
777 struct uvcg_format
*target_fmt
= NULL
;
778 struct uvcg_format_ptr
*format_ptr
, *tmp
;
780 src_hdr
= to_uvcg_streaming_header(src
);
781 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
783 opts_item
= src
->ci_parent
->ci_parent
->ci_parent
;
784 opts
= to_f_uvc_opts(opts_item
);
786 mutex_lock(&opts
->lock
);
787 target_fmt
= container_of(to_config_group(target
), struct uvcg_format
,
792 list_for_each_entry_safe(format_ptr
, tmp
, &src_hdr
->formats
, entry
)
793 if (format_ptr
->fmt
== target_fmt
) {
794 list_del(&format_ptr
->entry
);
801 mutex_unlock(&opts
->lock
);
802 mutex_unlock(su_mutex
);
805 static struct configfs_item_operations uvcg_streaming_header_item_ops
= {
806 .allow_link
= uvcg_streaming_header_allow_link
,
807 .drop_link
= uvcg_streaming_header_drop_link
,
810 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
811 static ssize_t uvcg_streaming_header_##cname##_show( \
812 struct config_item *item, char *page) \
814 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
815 struct f_uvc_opts *opts; \
816 struct config_item *opts_item; \
817 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
820 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
822 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
823 opts = to_f_uvc_opts(opts_item); \
825 mutex_lock(&opts->lock); \
826 result = sprintf(page, "%d\n", conv(sh->desc.aname)); \
827 mutex_unlock(&opts->lock); \
829 mutex_unlock(su_mutex); \
833 UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
835 #define identity_conv(x) (x)
837 UVCG_STREAMING_HEADER_ATTR(bm_info
, bmInfo
, identity_conv
);
838 UVCG_STREAMING_HEADER_ATTR(b_terminal_link
, bTerminalLink
, identity_conv
);
839 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method
, bStillCaptureMethod
,
841 UVCG_STREAMING_HEADER_ATTR(b_trigger_support
, bTriggerSupport
, identity_conv
);
842 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage
, bTriggerUsage
, identity_conv
);
846 #undef UVCG_STREAMING_HEADER_ATTR
848 static struct configfs_attribute
*uvcg_streaming_header_attrs
[] = {
849 &uvcg_streaming_header_attr_bm_info
,
850 &uvcg_streaming_header_attr_b_terminal_link
,
851 &uvcg_streaming_header_attr_b_still_capture_method
,
852 &uvcg_streaming_header_attr_b_trigger_support
,
853 &uvcg_streaming_header_attr_b_trigger_usage
,
857 static const struct config_item_type uvcg_streaming_header_type
= {
858 .ct_item_ops
= &uvcg_streaming_header_item_ops
,
859 .ct_attrs
= uvcg_streaming_header_attrs
,
860 .ct_owner
= THIS_MODULE
,
863 static struct config_item
864 *uvcg_streaming_header_make(struct config_group
*group
, const char *name
)
866 struct uvcg_streaming_header
*h
;
868 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
870 return ERR_PTR(-ENOMEM
);
872 INIT_LIST_HEAD(&h
->formats
);
873 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
874 h
->desc
.bDescriptorSubType
= UVC_VS_INPUT_HEADER
;
875 h
->desc
.bTerminalLink
= 3;
876 h
->desc
.bControlSize
= UVCG_STREAMING_CONTROL_SIZE
;
878 config_item_init_type_name(&h
->item
, name
, &uvcg_streaming_header_type
);
883 static void uvcg_streaming_header_drop(struct config_group
*group
,
884 struct config_item
*item
)
886 struct uvcg_streaming_header
*h
= to_uvcg_streaming_header(item
);
891 /* streaming/header */
892 static struct uvcg_streaming_header_grp
{
893 struct config_group group
;
894 } uvcg_streaming_header_grp
;
896 static struct configfs_group_operations uvcg_streaming_header_grp_ops
= {
897 .make_item
= uvcg_streaming_header_make
,
898 .drop_item
= uvcg_streaming_header_drop
,
901 static const struct config_item_type uvcg_streaming_header_grp_type
= {
902 .ct_group_ops
= &uvcg_streaming_header_grp_ops
,
903 .ct_owner
= THIS_MODULE
,
906 /* streaming/<mode>/<format>/<NAME> */
910 u8 b_descriptor_type
;
911 u8 b_descriptor_subtype
;
918 u32 dw_max_video_frame_buffer_size
;
919 u32 dw_default_frame_interval
;
920 u8 b_frame_interval_type
;
921 } __attribute__((packed
)) frame
;
922 u32
*dw_frame_interval
;
923 enum uvcg_format_type fmt_type
;
924 struct config_item item
;
927 static struct uvcg_frame
*to_uvcg_frame(struct config_item
*item
)
929 return container_of(item
, struct uvcg_frame
, item
);
932 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
933 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
935 struct uvcg_frame *f = to_uvcg_frame(item); \
936 struct f_uvc_opts *opts; \
937 struct config_item *opts_item; \
938 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
941 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
943 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
944 opts = to_f_uvc_opts(opts_item); \
946 mutex_lock(&opts->lock); \
947 result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \
948 mutex_unlock(&opts->lock); \
950 mutex_unlock(su_mutex); \
954 static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
955 const char *page, size_t len)\
957 struct uvcg_frame *f = to_uvcg_frame(item); \
958 struct f_uvc_opts *opts; \
959 struct config_item *opts_item; \
960 struct uvcg_format *fmt; \
961 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
965 ret = kstrtou##bits(page, 0, &num); \
969 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
971 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
972 opts = to_f_uvc_opts(opts_item); \
973 fmt = to_uvcg_format(f->item.ci_parent); \
975 mutex_lock(&opts->lock); \
976 if (fmt->linked || opts->refcnt) { \
981 f->frame.cname = to_little_endian(num); \
984 mutex_unlock(&opts->lock); \
985 mutex_unlock(su_mutex); \
989 UVC_ATTR(uvcg_frame_, cname, aname);
991 #define noop_conversion(x) (x)
993 UVCG_FRAME_ATTR(bm_capabilities
, bmCapabilities
, noop_conversion
,
995 UVCG_FRAME_ATTR(w_width
, wWidth
, le16_to_cpu
, cpu_to_le16
, 16);
996 UVCG_FRAME_ATTR(w_height
, wHeight
, le16_to_cpu
, cpu_to_le16
, 16);
997 UVCG_FRAME_ATTR(dw_min_bit_rate
, dwMinBitRate
, le32_to_cpu
, cpu_to_le32
, 32);
998 UVCG_FRAME_ATTR(dw_max_bit_rate
, dwMaxBitRate
, le32_to_cpu
, cpu_to_le32
, 32);
999 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size
, dwMaxVideoFrameBufferSize
,
1000 le32_to_cpu
, cpu_to_le32
, 32);
1001 UVCG_FRAME_ATTR(dw_default_frame_interval
, dwDefaultFrameInterval
,
1002 le32_to_cpu
, cpu_to_le32
, 32);
1004 #undef noop_conversion
1006 #undef UVCG_FRAME_ATTR
1008 static ssize_t
uvcg_frame_dw_frame_interval_show(struct config_item
*item
,
1011 struct uvcg_frame
*frm
= to_uvcg_frame(item
);
1012 struct f_uvc_opts
*opts
;
1013 struct config_item
*opts_item
;
1014 struct mutex
*su_mutex
= &frm
->item
.ci_group
->cg_subsys
->su_mutex
;
1018 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1020 opts_item
= frm
->item
.ci_parent
->ci_parent
->ci_parent
->ci_parent
;
1021 opts
= to_f_uvc_opts(opts_item
);
1023 mutex_lock(&opts
->lock
);
1024 for (result
= 0, i
= 0; i
< frm
->frame
.b_frame_interval_type
; ++i
) {
1025 result
+= sprintf(pg
, "%d\n",
1026 le32_to_cpu(frm
->dw_frame_interval
[i
]));
1029 mutex_unlock(&opts
->lock
);
1031 mutex_unlock(su_mutex
);
1035 static inline int __uvcg_count_frm_intrv(char *buf
, void *priv
)
1041 static inline int __uvcg_fill_frm_intrv(char *buf
, void *priv
)
1046 ret
= kstrtou32(buf
, 0, &num
);
1051 **interv
= cpu_to_le32(num
);
1057 static int __uvcg_iter_frm_intrv(const char *page
, size_t len
,
1058 int (*fun
)(char *, void *), void *priv
)
1060 /* sign, base 2 representation, newline, terminator */
1061 char buf
[1 + sizeof(u32
) * 8 + 1 + 1];
1062 const char *pg
= page
;
1068 while (pg
- page
< len
) {
1070 while (i
< sizeof(buf
) && (pg
- page
< len
) &&
1071 *pg
!= '\0' && *pg
!= '\n')
1073 if (i
== sizeof(buf
))
1075 while ((pg
- page
< len
) && (*pg
== '\0' || *pg
== '\n'))
1078 ret
= fun(buf
, priv
);
1086 static ssize_t
uvcg_frame_dw_frame_interval_store(struct config_item
*item
,
1087 const char *page
, size_t len
)
1089 struct uvcg_frame
*ch
= to_uvcg_frame(item
);
1090 struct f_uvc_opts
*opts
;
1091 struct config_item
*opts_item
;
1092 struct uvcg_format
*fmt
;
1093 struct mutex
*su_mutex
= &ch
->item
.ci_group
->cg_subsys
->su_mutex
;
1095 u32
*frm_intrv
, *tmp
;
1097 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1099 opts_item
= ch
->item
.ci_parent
->ci_parent
->ci_parent
->ci_parent
;
1100 opts
= to_f_uvc_opts(opts_item
);
1101 fmt
= to_uvcg_format(ch
->item
.ci_parent
);
1103 mutex_lock(&opts
->lock
);
1104 if (fmt
->linked
|| opts
->refcnt
) {
1109 ret
= __uvcg_iter_frm_intrv(page
, len
, __uvcg_count_frm_intrv
, &n
);
1113 tmp
= frm_intrv
= kcalloc(n
, sizeof(u32
), GFP_KERNEL
);
1119 ret
= __uvcg_iter_frm_intrv(page
, len
, __uvcg_fill_frm_intrv
, &tmp
);
1125 kfree(ch
->dw_frame_interval
);
1126 ch
->dw_frame_interval
= frm_intrv
;
1127 ch
->frame
.b_frame_interval_type
= n
;
1131 mutex_unlock(&opts
->lock
);
1132 mutex_unlock(su_mutex
);
1136 UVC_ATTR(uvcg_frame_
, dw_frame_interval
, dwFrameInterval
);
1138 static struct configfs_attribute
*uvcg_frame_attrs
[] = {
1139 &uvcg_frame_attr_bm_capabilities
,
1140 &uvcg_frame_attr_w_width
,
1141 &uvcg_frame_attr_w_height
,
1142 &uvcg_frame_attr_dw_min_bit_rate
,
1143 &uvcg_frame_attr_dw_max_bit_rate
,
1144 &uvcg_frame_attr_dw_max_video_frame_buffer_size
,
1145 &uvcg_frame_attr_dw_default_frame_interval
,
1146 &uvcg_frame_attr_dw_frame_interval
,
1150 static const struct config_item_type uvcg_frame_type
= {
1151 .ct_attrs
= uvcg_frame_attrs
,
1152 .ct_owner
= THIS_MODULE
,
1155 static struct config_item
*uvcg_frame_make(struct config_group
*group
,
1158 struct uvcg_frame
*h
;
1159 struct uvcg_format
*fmt
;
1160 struct f_uvc_opts
*opts
;
1161 struct config_item
*opts_item
;
1163 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1165 return ERR_PTR(-ENOMEM
);
1167 h
->frame
.b_descriptor_type
= USB_DT_CS_INTERFACE
;
1168 h
->frame
.b_frame_index
= 1;
1169 h
->frame
.w_width
= cpu_to_le16(640);
1170 h
->frame
.w_height
= cpu_to_le16(360);
1171 h
->frame
.dw_min_bit_rate
= cpu_to_le32(18432000);
1172 h
->frame
.dw_max_bit_rate
= cpu_to_le32(55296000);
1173 h
->frame
.dw_max_video_frame_buffer_size
= cpu_to_le32(460800);
1174 h
->frame
.dw_default_frame_interval
= cpu_to_le32(666666);
1176 opts_item
= group
->cg_item
.ci_parent
->ci_parent
->ci_parent
;
1177 opts
= to_f_uvc_opts(opts_item
);
1179 mutex_lock(&opts
->lock
);
1180 fmt
= to_uvcg_format(&group
->cg_item
);
1181 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1182 h
->frame
.b_descriptor_subtype
= UVC_VS_FRAME_UNCOMPRESSED
;
1183 h
->fmt_type
= UVCG_UNCOMPRESSED
;
1184 } else if (fmt
->type
== UVCG_MJPEG
) {
1185 h
->frame
.b_descriptor_subtype
= UVC_VS_FRAME_MJPEG
;
1186 h
->fmt_type
= UVCG_MJPEG
;
1188 mutex_unlock(&opts
->lock
);
1190 return ERR_PTR(-EINVAL
);
1193 mutex_unlock(&opts
->lock
);
1195 config_item_init_type_name(&h
->item
, name
, &uvcg_frame_type
);
1200 static void uvcg_frame_drop(struct config_group
*group
, struct config_item
*item
)
1202 struct uvcg_frame
*h
= to_uvcg_frame(item
);
1203 struct uvcg_format
*fmt
;
1204 struct f_uvc_opts
*opts
;
1205 struct config_item
*opts_item
;
1207 opts_item
= group
->cg_item
.ci_parent
->ci_parent
->ci_parent
;
1208 opts
= to_f_uvc_opts(opts_item
);
1210 mutex_lock(&opts
->lock
);
1211 fmt
= to_uvcg_format(&group
->cg_item
);
1214 mutex_unlock(&opts
->lock
);
1217 /* streaming/uncompressed/<NAME> */
1218 struct uvcg_uncompressed
{
1219 struct uvcg_format fmt
;
1220 struct uvc_format_uncompressed desc
;
1223 static struct uvcg_uncompressed
*to_uvcg_uncompressed(struct config_item
*item
)
1225 return container_of(
1226 container_of(to_config_group(item
), struct uvcg_format
, group
),
1227 struct uvcg_uncompressed
, fmt
);
1230 static struct configfs_group_operations uvcg_uncompressed_group_ops
= {
1231 .make_item
= uvcg_frame_make
,
1232 .drop_item
= uvcg_frame_drop
,
1235 static ssize_t
uvcg_uncompressed_guid_format_show(struct config_item
*item
,
1238 struct uvcg_uncompressed
*ch
= to_uvcg_uncompressed(item
);
1239 struct f_uvc_opts
*opts
;
1240 struct config_item
*opts_item
;
1241 struct mutex
*su_mutex
= &ch
->fmt
.group
.cg_subsys
->su_mutex
;
1243 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1245 opts_item
= ch
->fmt
.group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
1246 opts
= to_f_uvc_opts(opts_item
);
1248 mutex_lock(&opts
->lock
);
1249 memcpy(page
, ch
->desc
.guidFormat
, sizeof(ch
->desc
.guidFormat
));
1250 mutex_unlock(&opts
->lock
);
1252 mutex_unlock(su_mutex
);
1254 return sizeof(ch
->desc
.guidFormat
);
1257 static ssize_t
uvcg_uncompressed_guid_format_store(struct config_item
*item
,
1258 const char *page
, size_t len
)
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
;
1266 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1268 opts_item
= ch
->fmt
.group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
1269 opts
= to_f_uvc_opts(opts_item
);
1271 mutex_lock(&opts
->lock
);
1272 if (ch
->fmt
.linked
|| opts
->refcnt
) {
1277 memcpy(ch
->desc
.guidFormat
, page
,
1278 min(sizeof(ch
->desc
.guidFormat
), len
));
1279 ret
= sizeof(ch
->desc
.guidFormat
);
1282 mutex_unlock(&opts
->lock
);
1283 mutex_unlock(su_mutex
);
1287 UVC_ATTR(uvcg_uncompressed_
, guid_format
, guidFormat
);
1289 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
1290 static ssize_t uvcg_uncompressed_##cname##_show( \
1291 struct config_item *item, char *page) \
1293 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1294 struct f_uvc_opts *opts; \
1295 struct config_item *opts_item; \
1296 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1299 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1301 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1302 opts = to_f_uvc_opts(opts_item); \
1304 mutex_lock(&opts->lock); \
1305 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1306 mutex_unlock(&opts->lock); \
1308 mutex_unlock(su_mutex); \
1312 UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
1314 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
1315 static ssize_t uvcg_uncompressed_##cname##_show( \
1316 struct config_item *item, char *page) \
1318 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1319 struct f_uvc_opts *opts; \
1320 struct config_item *opts_item; \
1321 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1324 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1326 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1327 opts = to_f_uvc_opts(opts_item); \
1329 mutex_lock(&opts->lock); \
1330 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1331 mutex_unlock(&opts->lock); \
1333 mutex_unlock(su_mutex); \
1338 uvcg_uncompressed_##cname##_store(struct config_item *item, \
1339 const char *page, size_t len) \
1341 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1342 struct f_uvc_opts *opts; \
1343 struct config_item *opts_item; \
1344 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1348 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1350 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1351 opts = to_f_uvc_opts(opts_item); \
1353 mutex_lock(&opts->lock); \
1354 if (u->fmt.linked || opts->refcnt) { \
1359 ret = kstrtou8(page, 0, &num); \
1367 u->desc.aname = num; \
1370 mutex_unlock(&opts->lock); \
1371 mutex_unlock(su_mutex); \
1375 UVC_ATTR(uvcg_uncompressed_, cname, aname);
1377 #define identity_conv(x) (x)
1379 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel
, bBitsPerPixel
, identity_conv
);
1380 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index
, bDefaultFrameIndex
,
1382 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x
, bAspectRatioX
, identity_conv
);
1383 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y
, bAspectRatioY
, identity_conv
);
1384 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags
, bmInterfaceFlags
, identity_conv
);
1386 #undef identity_conv
1388 #undef UVCG_UNCOMPRESSED_ATTR
1389 #undef UVCG_UNCOMPRESSED_ATTR_RO
1391 static inline ssize_t
1392 uvcg_uncompressed_bma_controls_show(struct config_item
*item
, char *page
)
1394 struct uvcg_uncompressed
*unc
= to_uvcg_uncompressed(item
);
1395 return uvcg_format_bma_controls_show(&unc
->fmt
, page
);
1398 static inline ssize_t
1399 uvcg_uncompressed_bma_controls_store(struct config_item
*item
,
1400 const char *page
, size_t len
)
1402 struct uvcg_uncompressed
*unc
= to_uvcg_uncompressed(item
);
1403 return uvcg_format_bma_controls_store(&unc
->fmt
, page
, len
);
1406 UVC_ATTR(uvcg_uncompressed_
, bma_controls
, bmaControls
);
1408 static struct configfs_attribute
*uvcg_uncompressed_attrs
[] = {
1409 &uvcg_uncompressed_attr_guid_format
,
1410 &uvcg_uncompressed_attr_b_bits_per_pixel
,
1411 &uvcg_uncompressed_attr_b_default_frame_index
,
1412 &uvcg_uncompressed_attr_b_aspect_ratio_x
,
1413 &uvcg_uncompressed_attr_b_aspect_ratio_y
,
1414 &uvcg_uncompressed_attr_bm_interface_flags
,
1415 &uvcg_uncompressed_attr_bma_controls
,
1419 static const struct config_item_type uvcg_uncompressed_type
= {
1420 .ct_group_ops
= &uvcg_uncompressed_group_ops
,
1421 .ct_attrs
= uvcg_uncompressed_attrs
,
1422 .ct_owner
= THIS_MODULE
,
1425 static struct config_group
*uvcg_uncompressed_make(struct config_group
*group
,
1428 static char guid
[] = {
1429 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
1430 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1432 struct uvcg_uncompressed
*h
;
1434 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1436 return ERR_PTR(-ENOMEM
);
1438 h
->desc
.bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
;
1439 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
1440 h
->desc
.bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
;
1441 memcpy(h
->desc
.guidFormat
, guid
, sizeof(guid
));
1442 h
->desc
.bBitsPerPixel
= 16;
1443 h
->desc
.bDefaultFrameIndex
= 1;
1444 h
->desc
.bAspectRatioX
= 0;
1445 h
->desc
.bAspectRatioY
= 0;
1446 h
->desc
.bmInterfaceFlags
= 0;
1447 h
->desc
.bCopyProtect
= 0;
1449 h
->fmt
.type
= UVCG_UNCOMPRESSED
;
1450 config_group_init_type_name(&h
->fmt
.group
, name
,
1451 &uvcg_uncompressed_type
);
1453 return &h
->fmt
.group
;
1456 static void uvcg_uncompressed_drop(struct config_group
*group
,
1457 struct config_item
*item
)
1459 struct uvcg_uncompressed
*h
= to_uvcg_uncompressed(item
);
1464 static struct configfs_group_operations uvcg_uncompressed_grp_ops
= {
1465 .make_group
= uvcg_uncompressed_make
,
1466 .drop_item
= uvcg_uncompressed_drop
,
1469 static const struct config_item_type uvcg_uncompressed_grp_type
= {
1470 .ct_group_ops
= &uvcg_uncompressed_grp_ops
,
1471 .ct_owner
= THIS_MODULE
,
1474 /* streaming/mjpeg/<NAME> */
1476 struct uvcg_format fmt
;
1477 struct uvc_format_mjpeg desc
;
1480 static struct uvcg_mjpeg
*to_uvcg_mjpeg(struct config_item
*item
)
1482 return container_of(
1483 container_of(to_config_group(item
), struct uvcg_format
, group
),
1484 struct uvcg_mjpeg
, fmt
);
1487 static struct configfs_group_operations uvcg_mjpeg_group_ops
= {
1488 .make_item
= uvcg_frame_make
,
1489 .drop_item
= uvcg_frame_drop
,
1492 #define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
1493 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1495 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1496 struct f_uvc_opts *opts; \
1497 struct config_item *opts_item; \
1498 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1501 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1503 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1504 opts = to_f_uvc_opts(opts_item); \
1506 mutex_lock(&opts->lock); \
1507 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1508 mutex_unlock(&opts->lock); \
1510 mutex_unlock(su_mutex); \
1514 UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
1516 #define UVCG_MJPEG_ATTR(cname, aname, conv) \
1517 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1519 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1520 struct f_uvc_opts *opts; \
1521 struct config_item *opts_item; \
1522 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1525 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1527 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1528 opts = to_f_uvc_opts(opts_item); \
1530 mutex_lock(&opts->lock); \
1531 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1532 mutex_unlock(&opts->lock); \
1534 mutex_unlock(su_mutex); \
1539 uvcg_mjpeg_##cname##_store(struct config_item *item, \
1540 const char *page, size_t len) \
1542 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1543 struct f_uvc_opts *opts; \
1544 struct config_item *opts_item; \
1545 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1549 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1551 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1552 opts = to_f_uvc_opts(opts_item); \
1554 mutex_lock(&opts->lock); \
1555 if (u->fmt.linked || opts->refcnt) { \
1560 ret = kstrtou8(page, 0, &num); \
1568 u->desc.aname = num; \
1571 mutex_unlock(&opts->lock); \
1572 mutex_unlock(su_mutex); \
1576 UVC_ATTR(uvcg_mjpeg_, cname, aname)
1578 #define identity_conv(x) (x)
1580 UVCG_MJPEG_ATTR(b_default_frame_index
, bDefaultFrameIndex
,
1582 UVCG_MJPEG_ATTR_RO(bm_flags
, bmFlags
, identity_conv
);
1583 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x
, bAspectRatioX
, identity_conv
);
1584 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y
, bAspectRatioY
, identity_conv
);
1585 UVCG_MJPEG_ATTR_RO(bm_interface_flags
, bmInterfaceFlags
, identity_conv
);
1587 #undef identity_conv
1589 #undef UVCG_MJPEG_ATTR
1590 #undef UVCG_MJPEG_ATTR_RO
1592 static inline ssize_t
1593 uvcg_mjpeg_bma_controls_show(struct config_item
*item
, char *page
)
1595 struct uvcg_mjpeg
*u
= to_uvcg_mjpeg(item
);
1596 return uvcg_format_bma_controls_show(&u
->fmt
, page
);
1599 static inline ssize_t
1600 uvcg_mjpeg_bma_controls_store(struct config_item
*item
,
1601 const char *page
, size_t len
)
1603 struct uvcg_mjpeg
*u
= to_uvcg_mjpeg(item
);
1604 return uvcg_format_bma_controls_store(&u
->fmt
, page
, len
);
1607 UVC_ATTR(uvcg_mjpeg_
, bma_controls
, bmaControls
);
1609 static struct configfs_attribute
*uvcg_mjpeg_attrs
[] = {
1610 &uvcg_mjpeg_attr_b_default_frame_index
,
1611 &uvcg_mjpeg_attr_bm_flags
,
1612 &uvcg_mjpeg_attr_b_aspect_ratio_x
,
1613 &uvcg_mjpeg_attr_b_aspect_ratio_y
,
1614 &uvcg_mjpeg_attr_bm_interface_flags
,
1615 &uvcg_mjpeg_attr_bma_controls
,
1619 static const struct config_item_type uvcg_mjpeg_type
= {
1620 .ct_group_ops
= &uvcg_mjpeg_group_ops
,
1621 .ct_attrs
= uvcg_mjpeg_attrs
,
1622 .ct_owner
= THIS_MODULE
,
1625 static struct config_group
*uvcg_mjpeg_make(struct config_group
*group
,
1628 struct uvcg_mjpeg
*h
;
1630 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1632 return ERR_PTR(-ENOMEM
);
1634 h
->desc
.bLength
= UVC_DT_FORMAT_MJPEG_SIZE
;
1635 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
1636 h
->desc
.bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
;
1637 h
->desc
.bDefaultFrameIndex
= 1;
1638 h
->desc
.bAspectRatioX
= 0;
1639 h
->desc
.bAspectRatioY
= 0;
1640 h
->desc
.bmInterfaceFlags
= 0;
1641 h
->desc
.bCopyProtect
= 0;
1643 h
->fmt
.type
= UVCG_MJPEG
;
1644 config_group_init_type_name(&h
->fmt
.group
, name
,
1647 return &h
->fmt
.group
;
1650 static void uvcg_mjpeg_drop(struct config_group
*group
,
1651 struct config_item
*item
)
1653 struct uvcg_mjpeg
*h
= to_uvcg_mjpeg(item
);
1658 static struct configfs_group_operations uvcg_mjpeg_grp_ops
= {
1659 .make_group
= uvcg_mjpeg_make
,
1660 .drop_item
= uvcg_mjpeg_drop
,
1663 static const struct config_item_type uvcg_mjpeg_grp_type
= {
1664 .ct_group_ops
= &uvcg_mjpeg_grp_ops
,
1665 .ct_owner
= THIS_MODULE
,
1668 /* streaming/color_matching/default */
1669 static struct uvcg_default_color_matching
{
1670 struct config_group group
;
1671 } uvcg_default_color_matching
;
1673 static inline struct uvcg_default_color_matching
1674 *to_uvcg_default_color_matching(struct config_item
*item
)
1676 return container_of(to_config_group(item
),
1677 struct uvcg_default_color_matching
, group
);
1680 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
1681 static ssize_t uvcg_default_color_matching_##cname##_show( \
1682 struct config_item *item, char *page) \
1684 struct uvcg_default_color_matching *dc = \
1685 to_uvcg_default_color_matching(item); \
1686 struct f_uvc_opts *opts; \
1687 struct config_item *opts_item; \
1688 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
1689 struct uvc_color_matching_descriptor *cd; \
1692 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1694 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \
1695 opts = to_f_uvc_opts(opts_item); \
1696 cd = &opts->uvc_color_matching; \
1698 mutex_lock(&opts->lock); \
1699 result = sprintf(page, "%d\n", conv(cd->aname)); \
1700 mutex_unlock(&opts->lock); \
1702 mutex_unlock(su_mutex); \
1706 UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
1708 #define identity_conv(x) (x)
1710 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries
, bColorPrimaries
,
1712 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics
,
1713 bTransferCharacteristics
, identity_conv
);
1714 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients
, bMatrixCoefficients
,
1717 #undef identity_conv
1719 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1721 static struct configfs_attribute
*uvcg_default_color_matching_attrs
[] = {
1722 &uvcg_default_color_matching_attr_b_color_primaries
,
1723 &uvcg_default_color_matching_attr_b_transfer_characteristics
,
1724 &uvcg_default_color_matching_attr_b_matrix_coefficients
,
1728 static const struct config_item_type uvcg_default_color_matching_type
= {
1729 .ct_attrs
= uvcg_default_color_matching_attrs
,
1730 .ct_owner
= THIS_MODULE
,
1733 /* struct uvcg_color_matching {}; */
1735 /* streaming/color_matching */
1736 static struct uvcg_color_matching_grp
{
1737 struct config_group group
;
1738 } uvcg_color_matching_grp
;
1740 static const struct config_item_type uvcg_color_matching_grp_type
= {
1741 .ct_owner
= THIS_MODULE
,
1744 /* streaming/class/{fs|hs|ss} */
1745 static struct uvcg_streaming_class
{
1746 struct config_group group
;
1747 } uvcg_streaming_class_fs
, uvcg_streaming_class_hs
, uvcg_streaming_class_ss
;
1750 static inline struct uvc_descriptor_header
1751 ***__uvcg_get_stream_class_arr(struct config_item
*i
, struct f_uvc_opts
*o
)
1753 struct uvcg_streaming_class
*cl
= container_of(to_config_group(i
),
1754 struct uvcg_streaming_class
, group
);
1756 if (cl
== &uvcg_streaming_class_fs
)
1757 return &o
->uvc_fs_streaming_cls
;
1759 if (cl
== &uvcg_streaming_class_hs
)
1760 return &o
->uvc_hs_streaming_cls
;
1762 if (cl
== &uvcg_streaming_class_ss
)
1763 return &o
->uvc_ss_streaming_cls
;
1768 enum uvcg_strm_type
{
1775 * Iterate over a hierarchy of streaming descriptors' config items.
1776 * The items are created by the user with configfs.
1778 * It "processes" the header pointed to by @priv1, then for each format
1779 * that follows the header "processes" the format itself and then for
1780 * each frame inside a format "processes" the frame.
1782 * As a "processing" function the @fun is used.
1784 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
1785 * the amount of memory needed for an array of streaming descriptors
1786 * and second, to actually fill the array.
1788 * @h: streaming header pointer
1789 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
1790 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
1791 * @fun: callback function for processing each level of the hierarchy
1793 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header
*h
,
1794 void *priv2
, void *priv3
,
1795 int (*fun
)(void *, void *, void *, int, enum uvcg_strm_type type
))
1797 struct uvcg_format_ptr
*f
;
1798 struct config_group
*grp
;
1799 struct config_item
*item
;
1800 struct uvcg_frame
*frm
;
1807 ret
= fun(h
, priv2
, priv3
, 0, UVCG_HEADER
);
1810 list_for_each_entry(f
, &h
->formats
, entry
) {
1811 ret
= fun(f
->fmt
, priv2
, priv3
, i
++, UVCG_FORMAT
);
1814 grp
= &f
->fmt
->group
;
1815 list_for_each_entry(item
, &grp
->cg_children
, ci_entry
) {
1816 frm
= to_uvcg_frame(item
);
1817 ret
= fun(frm
, priv2
, priv3
, j
++, UVCG_FRAME
);
1827 * Count how many bytes are needed for an array of streaming descriptors.
1829 * @priv1: pointer to a header, format or frame
1830 * @priv2: inout parameter, accumulated size of the array
1831 * @priv3: inout parameter, accumulated number of the array elements
1832 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
1834 static int __uvcg_cnt_strm(void *priv1
, void *priv2
, void *priv3
, int n
,
1835 enum uvcg_strm_type type
)
1837 size_t *size
= priv2
;
1838 size_t *count
= priv3
;
1842 struct uvcg_streaming_header
*h
= priv1
;
1844 *size
+= sizeof(h
->desc
);
1846 *size
+= h
->num_fmt
* UVCG_STREAMING_CONTROL_SIZE
;
1850 struct uvcg_format
*fmt
= priv1
;
1852 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1853 struct uvcg_uncompressed
*u
=
1854 container_of(fmt
, struct uvcg_uncompressed
,
1857 *size
+= sizeof(u
->desc
);
1858 } else if (fmt
->type
== UVCG_MJPEG
) {
1859 struct uvcg_mjpeg
*m
=
1860 container_of(fmt
, struct uvcg_mjpeg
, fmt
);
1862 *size
+= sizeof(m
->desc
);
1869 struct uvcg_frame
*frm
= priv1
;
1870 int sz
= sizeof(frm
->dw_frame_interval
);
1872 *size
+= sizeof(frm
->frame
);
1873 *size
+= frm
->frame
.b_frame_interval_type
* sz
;
1884 * Fill an array of streaming descriptors.
1886 * @priv1: pointer to a header, format or frame
1887 * @priv2: inout parameter, pointer into a block of memory
1888 * @priv3: inout parameter, pointer to a 2-dimensional array
1890 static int __uvcg_fill_strm(void *priv1
, void *priv2
, void *priv3
, int n
,
1891 enum uvcg_strm_type type
)
1893 void **dest
= priv2
;
1894 struct uvc_descriptor_header
***array
= priv3
;
1902 struct uvc_input_header_descriptor
*ihdr
= *dest
;
1903 struct uvcg_streaming_header
*h
= priv1
;
1904 struct uvcg_format_ptr
*f
;
1906 memcpy(*dest
, &h
->desc
, sizeof(h
->desc
));
1907 *dest
+= sizeof(h
->desc
);
1908 sz
= UVCG_STREAMING_CONTROL_SIZE
;
1909 list_for_each_entry(f
, &h
->formats
, entry
) {
1910 memcpy(*dest
, f
->fmt
->bmaControls
, sz
);
1913 ihdr
->bLength
= sizeof(h
->desc
) + h
->num_fmt
* sz
;
1914 ihdr
->bNumFormats
= h
->num_fmt
;
1918 struct uvcg_format
*fmt
= priv1
;
1920 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1921 struct uvc_format_uncompressed
*unc
= *dest
;
1922 struct uvcg_uncompressed
*u
=
1923 container_of(fmt
, struct uvcg_uncompressed
,
1926 memcpy(*dest
, &u
->desc
, sizeof(u
->desc
));
1927 *dest
+= sizeof(u
->desc
);
1928 unc
->bNumFrameDescriptors
= fmt
->num_frames
;
1929 unc
->bFormatIndex
= n
+ 1;
1930 } else if (fmt
->type
== UVCG_MJPEG
) {
1931 struct uvc_format_mjpeg
*mjp
= *dest
;
1932 struct uvcg_mjpeg
*m
=
1933 container_of(fmt
, struct uvcg_mjpeg
, fmt
);
1935 memcpy(*dest
, &m
->desc
, sizeof(m
->desc
));
1936 *dest
+= sizeof(m
->desc
);
1937 mjp
->bNumFrameDescriptors
= fmt
->num_frames
;
1938 mjp
->bFormatIndex
= n
+ 1;
1945 struct uvcg_frame
*frm
= priv1
;
1946 struct uvc_descriptor_header
*h
= *dest
;
1948 sz
= sizeof(frm
->frame
);
1949 memcpy(*dest
, &frm
->frame
, sz
);
1951 sz
= frm
->frame
.b_frame_interval_type
*
1952 sizeof(*frm
->dw_frame_interval
);
1953 memcpy(*dest
, frm
->dw_frame_interval
, sz
);
1955 if (frm
->fmt_type
== UVCG_UNCOMPRESSED
)
1956 h
->bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(
1957 frm
->frame
.b_frame_interval_type
);
1958 else if (frm
->fmt_type
== UVCG_MJPEG
)
1959 h
->bLength
= UVC_DT_FRAME_MJPEG_SIZE(
1960 frm
->frame
.b_frame_interval_type
);
1968 static int uvcg_streaming_class_allow_link(struct config_item
*src
,
1969 struct config_item
*target
)
1971 struct config_item
*streaming
, *header
;
1972 struct f_uvc_opts
*opts
;
1973 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
1974 struct uvc_descriptor_header
***class_array
, **cl_arr
;
1975 struct uvcg_streaming_header
*target_hdr
;
1976 void *data
, *data_save
;
1977 size_t size
= 0, count
= 0;
1980 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1982 streaming
= src
->ci_parent
->ci_parent
;
1983 header
= config_group_find_item(to_config_group(streaming
), "header");
1984 if (!header
|| target
->ci_parent
!= header
)
1987 opts
= to_f_uvc_opts(streaming
->ci_parent
);
1989 mutex_lock(&opts
->lock
);
1991 class_array
= __uvcg_get_stream_class_arr(src
, opts
);
1992 if (!class_array
|| *class_array
|| opts
->refcnt
) {
1997 target_hdr
= to_uvcg_streaming_header(target
);
1998 ret
= __uvcg_iter_strm_cls(target_hdr
, &size
, &count
, __uvcg_cnt_strm
);
2002 count
+= 2; /* color_matching, NULL */
2003 *class_array
= kcalloc(count
, sizeof(void *), GFP_KERNEL
);
2004 if (!*class_array
) {
2009 data
= data_save
= kzalloc(size
, GFP_KERNEL
);
2011 kfree(*class_array
);
2012 *class_array
= NULL
;
2016 cl_arr
= *class_array
;
2017 ret
= __uvcg_iter_strm_cls(target_hdr
, &data
, &cl_arr
,
2020 kfree(*class_array
);
2021 *class_array
= NULL
;
2023 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2024 * might have advanced the "data", so use a backup copy
2029 *cl_arr
= (struct uvc_descriptor_header
*)&opts
->uvc_color_matching
;
2031 ++target_hdr
->linked
;
2035 mutex_unlock(&opts
->lock
);
2037 mutex_unlock(su_mutex
);
2041 static void uvcg_streaming_class_drop_link(struct config_item
*src
,
2042 struct config_item
*target
)
2044 struct config_item
*streaming
, *header
;
2045 struct f_uvc_opts
*opts
;
2046 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
2047 struct uvc_descriptor_header
***class_array
;
2048 struct uvcg_streaming_header
*target_hdr
;
2050 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
2052 streaming
= src
->ci_parent
->ci_parent
;
2053 header
= config_group_find_item(to_config_group(streaming
), "header");
2054 if (!header
|| target
->ci_parent
!= header
)
2057 opts
= to_f_uvc_opts(streaming
->ci_parent
);
2059 mutex_lock(&opts
->lock
);
2061 class_array
= __uvcg_get_stream_class_arr(src
, opts
);
2062 if (!class_array
|| !*class_array
)
2068 target_hdr
= to_uvcg_streaming_header(target
);
2069 --target_hdr
->linked
;
2070 kfree(**class_array
);
2071 kfree(*class_array
);
2072 *class_array
= NULL
;
2075 mutex_unlock(&opts
->lock
);
2077 mutex_unlock(su_mutex
);
2080 static struct configfs_item_operations uvcg_streaming_class_item_ops
= {
2081 .allow_link
= uvcg_streaming_class_allow_link
,
2082 .drop_link
= uvcg_streaming_class_drop_link
,
2085 static const struct config_item_type uvcg_streaming_class_type
= {
2086 .ct_item_ops
= &uvcg_streaming_class_item_ops
,
2087 .ct_owner
= THIS_MODULE
,
2090 /* streaming/class */
2091 static struct uvcg_streaming_class_grp
{
2092 struct config_group group
;
2093 } uvcg_streaming_class_grp
;
2095 static const struct config_item_type uvcg_streaming_class_grp_type
= {
2096 .ct_owner
= THIS_MODULE
,
2100 static struct uvcg_streaming_grp
{
2101 struct config_group group
;
2102 } uvcg_streaming_grp
;
2104 static const struct config_item_type uvcg_streaming_grp_type
= {
2105 .ct_owner
= THIS_MODULE
,
2108 static inline struct f_uvc_opts
*to_f_uvc_opts(struct config_item
*item
)
2110 return container_of(to_config_group(item
), struct f_uvc_opts
,
2114 static void uvc_attr_release(struct config_item
*item
)
2116 struct f_uvc_opts
*opts
= to_f_uvc_opts(item
);
2118 usb_put_function_instance(&opts
->func_inst
);
2121 static struct configfs_item_operations uvc_item_ops
= {
2122 .release
= uvc_attr_release
,
2125 #define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
2126 static ssize_t f_uvc_opts_##cname##_show( \
2127 struct config_item *item, char *page) \
2129 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2132 mutex_lock(&opts->lock); \
2133 result = sprintf(page, "%d\n", conv(opts->cname)); \
2134 mutex_unlock(&opts->lock); \
2140 f_uvc_opts_##cname##_store(struct config_item *item, \
2141 const char *page, size_t len) \
2143 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2147 mutex_lock(&opts->lock); \
2148 if (opts->refcnt) { \
2153 ret = str2u(page, 0, &num); \
2157 if (num > limit) { \
2161 opts->cname = vnoc(num); \
2164 mutex_unlock(&opts->lock); \
2168 UVC_ATTR(f_uvc_opts_, cname, cname)
2170 #define identity_conv(x) (x)
2172 UVCG_OPTS_ATTR(streaming_interval
, streaming_interval
, identity_conv
,
2173 kstrtou8
, u8
, identity_conv
, 16);
2174 UVCG_OPTS_ATTR(streaming_maxpacket
, streaming_maxpacket
, le16_to_cpu
,
2175 kstrtou16
, u16
, le16_to_cpu
, 3072);
2176 UVCG_OPTS_ATTR(streaming_maxburst
, streaming_maxburst
, identity_conv
,
2177 kstrtou8
, u8
, identity_conv
, 15);
2179 #undef identity_conv
2181 #undef UVCG_OPTS_ATTR
2183 static struct configfs_attribute
*uvc_attrs
[] = {
2184 &f_uvc_opts_attr_streaming_interval
,
2185 &f_uvc_opts_attr_streaming_maxpacket
,
2186 &f_uvc_opts_attr_streaming_maxburst
,
2190 static const struct config_item_type uvc_func_type
= {
2191 .ct_item_ops
= &uvc_item_ops
,
2192 .ct_attrs
= uvc_attrs
,
2193 .ct_owner
= THIS_MODULE
,
2196 int uvcg_attach_configfs(struct f_uvc_opts
*opts
)
2198 config_group_init_type_name(&uvcg_control_header_grp
.group
,
2200 &uvcg_control_header_grp_type
);
2202 config_group_init_type_name(&uvcg_default_processing
.group
,
2203 "default", &uvcg_default_processing_type
);
2204 config_group_init_type_name(&uvcg_processing_grp
.group
,
2205 "processing", &uvcg_processing_grp_type
);
2206 configfs_add_default_group(&uvcg_default_processing
.group
,
2207 &uvcg_processing_grp
.group
);
2209 config_group_init_type_name(&uvcg_default_camera
.group
,
2210 "default", &uvcg_default_camera_type
);
2211 config_group_init_type_name(&uvcg_camera_grp
.group
,
2212 "camera", &uvcg_camera_grp_type
);
2213 configfs_add_default_group(&uvcg_default_camera
.group
,
2214 &uvcg_camera_grp
.group
);
2216 config_group_init_type_name(&uvcg_default_output
.group
,
2217 "default", &uvcg_default_output_type
);
2218 config_group_init_type_name(&uvcg_output_grp
.group
,
2219 "output", &uvcg_output_grp_type
);
2220 configfs_add_default_group(&uvcg_default_output
.group
,
2221 &uvcg_output_grp
.group
);
2223 config_group_init_type_name(&uvcg_terminal_grp
.group
,
2224 "terminal", &uvcg_terminal_grp_type
);
2225 configfs_add_default_group(&uvcg_camera_grp
.group
,
2226 &uvcg_terminal_grp
.group
);
2227 configfs_add_default_group(&uvcg_output_grp
.group
,
2228 &uvcg_terminal_grp
.group
);
2230 config_group_init_type_name(&uvcg_control_class_fs
.group
,
2231 "fs", &uvcg_control_class_type
);
2232 config_group_init_type_name(&uvcg_control_class_ss
.group
,
2233 "ss", &uvcg_control_class_type
);
2234 config_group_init_type_name(&uvcg_control_class_grp
.group
,
2236 &uvcg_control_class_grp_type
);
2237 configfs_add_default_group(&uvcg_control_class_fs
.group
,
2238 &uvcg_control_class_grp
.group
);
2239 configfs_add_default_group(&uvcg_control_class_ss
.group
,
2240 &uvcg_control_class_grp
.group
);
2242 config_group_init_type_name(&uvcg_control_grp
.group
,
2244 &uvcg_control_grp_type
);
2245 configfs_add_default_group(&uvcg_control_header_grp
.group
,
2246 &uvcg_control_grp
.group
);
2247 configfs_add_default_group(&uvcg_processing_grp
.group
,
2248 &uvcg_control_grp
.group
);
2249 configfs_add_default_group(&uvcg_terminal_grp
.group
,
2250 &uvcg_control_grp
.group
);
2251 configfs_add_default_group(&uvcg_control_class_grp
.group
,
2252 &uvcg_control_grp
.group
);
2254 config_group_init_type_name(&uvcg_streaming_header_grp
.group
,
2256 &uvcg_streaming_header_grp_type
);
2257 config_group_init_type_name(&uvcg_uncompressed_grp
.group
,
2259 &uvcg_uncompressed_grp_type
);
2260 config_group_init_type_name(&uvcg_mjpeg_grp
.group
,
2262 &uvcg_mjpeg_grp_type
);
2263 config_group_init_type_name(&uvcg_default_color_matching
.group
,
2265 &uvcg_default_color_matching_type
);
2266 config_group_init_type_name(&uvcg_color_matching_grp
.group
,
2268 &uvcg_color_matching_grp_type
);
2269 configfs_add_default_group(&uvcg_default_color_matching
.group
,
2270 &uvcg_color_matching_grp
.group
);
2272 config_group_init_type_name(&uvcg_streaming_class_fs
.group
,
2273 "fs", &uvcg_streaming_class_type
);
2274 config_group_init_type_name(&uvcg_streaming_class_hs
.group
,
2275 "hs", &uvcg_streaming_class_type
);
2276 config_group_init_type_name(&uvcg_streaming_class_ss
.group
,
2277 "ss", &uvcg_streaming_class_type
);
2278 config_group_init_type_name(&uvcg_streaming_class_grp
.group
,
2279 "class", &uvcg_streaming_class_grp_type
);
2280 configfs_add_default_group(&uvcg_streaming_class_fs
.group
,
2281 &uvcg_streaming_class_grp
.group
);
2282 configfs_add_default_group(&uvcg_streaming_class_hs
.group
,
2283 &uvcg_streaming_class_grp
.group
);
2284 configfs_add_default_group(&uvcg_streaming_class_ss
.group
,
2285 &uvcg_streaming_class_grp
.group
);
2287 config_group_init_type_name(&uvcg_streaming_grp
.group
,
2288 "streaming", &uvcg_streaming_grp_type
);
2289 configfs_add_default_group(&uvcg_streaming_header_grp
.group
,
2290 &uvcg_streaming_grp
.group
);
2291 configfs_add_default_group(&uvcg_uncompressed_grp
.group
,
2292 &uvcg_streaming_grp
.group
);
2293 configfs_add_default_group(&uvcg_mjpeg_grp
.group
,
2294 &uvcg_streaming_grp
.group
);
2295 configfs_add_default_group(&uvcg_color_matching_grp
.group
,
2296 &uvcg_streaming_grp
.group
);
2297 configfs_add_default_group(&uvcg_streaming_class_grp
.group
,
2298 &uvcg_streaming_grp
.group
);
2300 config_group_init_type_name(&opts
->func_inst
.group
,
2303 configfs_add_default_group(&uvcg_control_grp
.group
,
2304 &opts
->func_inst
.group
);
2305 configfs_add_default_group(&uvcg_streaming_grp
.group
,
2306 &opts
->func_inst
.group
);