4 * Configfs support for the uvc function.
6 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 * http://www.samsung.com
9 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
16 #include "uvc_configfs.h"
18 #define UVCG_STREAMING_CONTROL_SIZE 1
20 #define UVC_ATTR(prefix, cname, aname) \
21 static struct configfs_attribute prefix##attr_##cname = { \
22 .ca_name = __stringify(aname), \
23 .ca_mode = S_IRUGO | S_IWUGO, \
24 .ca_owner = THIS_MODULE, \
25 .show = prefix##cname##_show, \
26 .store = prefix##cname##_store, \
29 #define UVC_ATTR_RO(prefix, cname, aname) \
30 static struct configfs_attribute prefix##attr_##cname = { \
31 .ca_name = __stringify(aname), \
33 .ca_owner = THIS_MODULE, \
34 .show = prefix##cname##_show, \
37 static inline struct f_uvc_opts
*to_f_uvc_opts(struct config_item
*item
);
39 /* control/header/<NAME> */
40 DECLARE_UVC_HEADER_DESCRIPTOR(1);
42 struct uvcg_control_header
{
43 struct config_item item
;
44 struct UVC_HEADER_DESCRIPTOR(1) desc
;
48 static struct uvcg_control_header
*to_uvcg_control_header(struct config_item
*item
)
50 return container_of(item
, struct uvcg_control_header
, item
);
53 #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
54 static ssize_t uvcg_control_header_##cname##_show( \
55 struct config_item *item, char *page) \
57 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
58 struct f_uvc_opts *opts; \
59 struct config_item *opts_item; \
60 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
63 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
65 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
66 opts = to_f_uvc_opts(opts_item); \
68 mutex_lock(&opts->lock); \
69 result = sprintf(page, "%d\n", conv(ch->desc.aname)); \
70 mutex_unlock(&opts->lock); \
72 mutex_unlock(su_mutex); \
77 uvcg_control_header_##cname##_store(struct config_item *item, \
78 const char *page, size_t len) \
80 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
81 struct f_uvc_opts *opts; \
82 struct config_item *opts_item; \
83 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
87 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
89 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
90 opts = to_f_uvc_opts(opts_item); \
92 mutex_lock(&opts->lock); \
93 if (ch->linked || opts->refcnt) { \
98 ret = str2u(page, 0, &num); \
106 ch->desc.aname = vnoc(num); \
109 mutex_unlock(&opts->lock); \
110 mutex_unlock(su_mutex); \
114 UVC_ATTR(uvcg_control_header_, cname, aname)
116 UVCG_CTRL_HDR_ATTR(bcd_uvc
, bcdUVC
, le16_to_cpu
, kstrtou16
, u16
, cpu_to_le16
,
119 UVCG_CTRL_HDR_ATTR(dw_clock_frequency
, dwClockFrequency
, le32_to_cpu
, kstrtou32
,
120 u32
, cpu_to_le32
, 0x7fffffff);
122 #undef UVCG_CTRL_HDR_ATTR
124 static struct configfs_attribute
*uvcg_control_header_attrs
[] = {
125 &uvcg_control_header_attr_bcd_uvc
,
126 &uvcg_control_header_attr_dw_clock_frequency
,
130 static struct config_item_type uvcg_control_header_type
= {
131 .ct_attrs
= uvcg_control_header_attrs
,
132 .ct_owner
= THIS_MODULE
,
135 static struct config_item
*uvcg_control_header_make(struct config_group
*group
,
138 struct uvcg_control_header
*h
;
140 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
142 return ERR_PTR(-ENOMEM
);
144 h
->desc
.bLength
= UVC_DT_HEADER_SIZE(1);
145 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
146 h
->desc
.bDescriptorSubType
= UVC_VC_HEADER
;
147 h
->desc
.bcdUVC
= cpu_to_le16(0x0100);
148 h
->desc
.dwClockFrequency
= cpu_to_le32(48000000);
150 config_item_init_type_name(&h
->item
, name
, &uvcg_control_header_type
);
155 static void uvcg_control_header_drop(struct config_group
*group
,
156 struct config_item
*item
)
158 struct uvcg_control_header
*h
= to_uvcg_control_header(item
);
164 static struct uvcg_control_header_grp
{
165 struct config_group group
;
166 } uvcg_control_header_grp
;
168 static struct configfs_group_operations uvcg_control_header_grp_ops
= {
169 .make_item
= uvcg_control_header_make
,
170 .drop_item
= uvcg_control_header_drop
,
173 static struct config_item_type uvcg_control_header_grp_type
= {
174 .ct_group_ops
= &uvcg_control_header_grp_ops
,
175 .ct_owner
= THIS_MODULE
,
178 /* control/processing/default */
179 static struct uvcg_default_processing
{
180 struct config_group group
;
181 } uvcg_default_processing
;
183 static inline struct uvcg_default_processing
184 *to_uvcg_default_processing(struct config_item
*item
)
186 return container_of(to_config_group(item
),
187 struct uvcg_default_processing
, group
);
190 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
191 static ssize_t uvcg_default_processing_##cname##_show( \
192 struct config_item *item, char *page) \
194 struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
195 struct f_uvc_opts *opts; \
196 struct config_item *opts_item; \
197 struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
198 struct uvc_processing_unit_descriptor *pd; \
201 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
203 opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \
204 opts = to_f_uvc_opts(opts_item); \
205 pd = &opts->uvc_processing; \
207 mutex_lock(&opts->lock); \
208 result = sprintf(page, "%d\n", conv(pd->aname)); \
209 mutex_unlock(&opts->lock); \
211 mutex_unlock(su_mutex); \
215 UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
217 #define identity_conv(x) (x)
219 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id
, bUnitID
, identity_conv
);
220 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id
, bSourceID
, identity_conv
);
221 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier
, wMaxMultiplier
, le16_to_cpu
);
222 UVCG_DEFAULT_PROCESSING_ATTR(i_processing
, iProcessing
, identity_conv
);
226 #undef UVCG_DEFAULT_PROCESSING_ATTR
228 static ssize_t
uvcg_default_processing_bm_controls_show(
229 struct config_item
*item
, char *page
)
231 struct uvcg_default_processing
*dp
= to_uvcg_default_processing(item
);
232 struct f_uvc_opts
*opts
;
233 struct config_item
*opts_item
;
234 struct mutex
*su_mutex
= &dp
->group
.cg_subsys
->su_mutex
;
235 struct uvc_processing_unit_descriptor
*pd
;
239 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
241 opts_item
= dp
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
242 opts
= to_f_uvc_opts(opts_item
);
243 pd
= &opts
->uvc_processing
;
245 mutex_lock(&opts
->lock
);
246 for (result
= 0, i
= 0; i
< pd
->bControlSize
; ++i
) {
247 result
+= sprintf(pg
, "%d\n", pd
->bmControls
[i
]);
250 mutex_unlock(&opts
->lock
);
252 mutex_unlock(su_mutex
);
257 UVC_ATTR_RO(uvcg_default_processing_
, bm_controls
, bmControls
);
259 static struct configfs_attribute
*uvcg_default_processing_attrs
[] = {
260 &uvcg_default_processing_attr_b_unit_id
,
261 &uvcg_default_processing_attr_b_source_id
,
262 &uvcg_default_processing_attr_w_max_multiplier
,
263 &uvcg_default_processing_attr_bm_controls
,
264 &uvcg_default_processing_attr_i_processing
,
268 static struct config_item_type uvcg_default_processing_type
= {
269 .ct_attrs
= uvcg_default_processing_attrs
,
270 .ct_owner
= THIS_MODULE
,
273 /* struct uvcg_processing {}; */
275 /* control/processing */
276 static struct uvcg_processing_grp
{
277 struct config_group group
;
278 } uvcg_processing_grp
;
280 static struct config_item_type uvcg_processing_grp_type
= {
281 .ct_owner
= THIS_MODULE
,
284 /* control/terminal/camera/default */
285 static struct uvcg_default_camera
{
286 struct config_group group
;
287 } uvcg_default_camera
;
289 static inline struct uvcg_default_camera
290 *to_uvcg_default_camera(struct config_item
*item
)
292 return container_of(to_config_group(item
),
293 struct uvcg_default_camera
, group
);
296 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
297 static ssize_t uvcg_default_camera_##cname##_show( \
298 struct config_item *item, char *page) \
300 struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \
301 struct f_uvc_opts *opts; \
302 struct config_item *opts_item; \
303 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
304 struct uvc_camera_terminal_descriptor *cd; \
307 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
309 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> \
311 opts = to_f_uvc_opts(opts_item); \
312 cd = &opts->uvc_camera_terminal; \
314 mutex_lock(&opts->lock); \
315 result = sprintf(page, "%d\n", conv(cd->aname)); \
316 mutex_unlock(&opts->lock); \
318 mutex_unlock(su_mutex); \
323 UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
325 #define identity_conv(x) (x)
327 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id
, bTerminalID
, identity_conv
);
328 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type
, wTerminalType
, le16_to_cpu
);
329 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal
, bAssocTerminal
, identity_conv
);
330 UVCG_DEFAULT_CAMERA_ATTR(i_terminal
, iTerminal
, identity_conv
);
331 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min
, wObjectiveFocalLengthMin
,
333 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max
, wObjectiveFocalLengthMax
,
335 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length
, wOcularFocalLength
,
340 #undef UVCG_DEFAULT_CAMERA_ATTR
342 static ssize_t
uvcg_default_camera_bm_controls_show(
343 struct config_item
*item
, char *page
)
345 struct uvcg_default_camera
*dc
= to_uvcg_default_camera(item
);
346 struct f_uvc_opts
*opts
;
347 struct config_item
*opts_item
;
348 struct mutex
*su_mutex
= &dc
->group
.cg_subsys
->su_mutex
;
349 struct uvc_camera_terminal_descriptor
*cd
;
353 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
355 opts_item
= dc
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
->
357 opts
= to_f_uvc_opts(opts_item
);
358 cd
= &opts
->uvc_camera_terminal
;
360 mutex_lock(&opts
->lock
);
361 for (result
= 0, i
= 0; i
< cd
->bControlSize
; ++i
) {
362 result
+= sprintf(pg
, "%d\n", cd
->bmControls
[i
]);
365 mutex_unlock(&opts
->lock
);
367 mutex_unlock(su_mutex
);
371 UVC_ATTR_RO(uvcg_default_camera_
, bm_controls
, bmControls
);
373 static struct configfs_attribute
*uvcg_default_camera_attrs
[] = {
374 &uvcg_default_camera_attr_b_terminal_id
,
375 &uvcg_default_camera_attr_w_terminal_type
,
376 &uvcg_default_camera_attr_b_assoc_terminal
,
377 &uvcg_default_camera_attr_i_terminal
,
378 &uvcg_default_camera_attr_w_objective_focal_length_min
,
379 &uvcg_default_camera_attr_w_objective_focal_length_max
,
380 &uvcg_default_camera_attr_w_ocular_focal_length
,
381 &uvcg_default_camera_attr_bm_controls
,
385 static struct config_item_type uvcg_default_camera_type
= {
386 .ct_attrs
= uvcg_default_camera_attrs
,
387 .ct_owner
= THIS_MODULE
,
390 /* struct uvcg_camera {}; */
392 /* control/terminal/camera */
393 static struct uvcg_camera_grp
{
394 struct config_group group
;
397 static struct config_item_type uvcg_camera_grp_type
= {
398 .ct_owner
= THIS_MODULE
,
401 /* control/terminal/output/default */
402 static struct uvcg_default_output
{
403 struct config_group group
;
404 } uvcg_default_output
;
406 static inline struct uvcg_default_output
407 *to_uvcg_default_output(struct config_item
*item
)
409 return container_of(to_config_group(item
),
410 struct uvcg_default_output
, group
);
413 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
414 static ssize_t uvcg_default_output_##cname##_show( \
415 struct config_item *item, char *page) \
417 struct uvcg_default_output *dout = to_uvcg_default_output(item); \
418 struct f_uvc_opts *opts; \
419 struct config_item *opts_item; \
420 struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
421 struct uvc_output_terminal_descriptor *cd; \
424 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
426 opts_item = dout->group.cg_item.ci_parent->ci_parent-> \
427 ci_parent->ci_parent; \
428 opts = to_f_uvc_opts(opts_item); \
429 cd = &opts->uvc_output_terminal; \
431 mutex_lock(&opts->lock); \
432 result = sprintf(page, "%d\n", conv(cd->aname)); \
433 mutex_unlock(&opts->lock); \
435 mutex_unlock(su_mutex); \
440 UVC_ATTR_RO(uvcg_default_output_, cname, aname)
442 #define identity_conv(x) (x)
444 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id
, bTerminalID
, identity_conv
);
445 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type
, wTerminalType
, le16_to_cpu
);
446 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal
, bAssocTerminal
, identity_conv
);
447 UVCG_DEFAULT_OUTPUT_ATTR(b_source_id
, bSourceID
, identity_conv
);
448 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal
, iTerminal
, identity_conv
);
452 #undef UVCG_DEFAULT_OUTPUT_ATTR
454 static struct configfs_attribute
*uvcg_default_output_attrs
[] = {
455 &uvcg_default_output_attr_b_terminal_id
,
456 &uvcg_default_output_attr_w_terminal_type
,
457 &uvcg_default_output_attr_b_assoc_terminal
,
458 &uvcg_default_output_attr_b_source_id
,
459 &uvcg_default_output_attr_i_terminal
,
463 static struct config_item_type uvcg_default_output_type
= {
464 .ct_attrs
= uvcg_default_output_attrs
,
465 .ct_owner
= THIS_MODULE
,
468 /* struct uvcg_output {}; */
470 /* control/terminal/output */
471 static struct uvcg_output_grp
{
472 struct config_group group
;
475 static struct config_item_type uvcg_output_grp_type
= {
476 .ct_owner
= THIS_MODULE
,
479 /* control/terminal */
480 static struct uvcg_terminal_grp
{
481 struct config_group group
;
484 static struct config_item_type uvcg_terminal_grp_type
= {
485 .ct_owner
= THIS_MODULE
,
488 /* control/class/{fs} */
489 static struct uvcg_control_class
{
490 struct config_group group
;
491 } uvcg_control_class_fs
, uvcg_control_class_ss
;
494 static inline struct uvc_descriptor_header
495 **uvcg_get_ctl_class_arr(struct config_item
*i
, struct f_uvc_opts
*o
)
497 struct uvcg_control_class
*cl
= container_of(to_config_group(i
),
498 struct uvcg_control_class
, group
);
500 if (cl
== &uvcg_control_class_fs
)
501 return o
->uvc_fs_control_cls
;
503 if (cl
== &uvcg_control_class_ss
)
504 return o
->uvc_ss_control_cls
;
509 static int uvcg_control_class_allow_link(struct config_item
*src
,
510 struct config_item
*target
)
512 struct config_item
*control
, *header
;
513 struct f_uvc_opts
*opts
;
514 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
515 struct uvc_descriptor_header
**class_array
;
516 struct uvcg_control_header
*target_hdr
;
519 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
521 control
= src
->ci_parent
->ci_parent
;
522 header
= config_group_find_item(to_config_group(control
), "header");
523 if (!header
|| target
->ci_parent
!= header
)
526 opts
= to_f_uvc_opts(control
->ci_parent
);
528 mutex_lock(&opts
->lock
);
530 class_array
= uvcg_get_ctl_class_arr(src
, opts
);
533 if (opts
->refcnt
|| class_array
[0]) {
538 target_hdr
= to_uvcg_control_header(target
);
539 ++target_hdr
->linked
;
540 class_array
[0] = (struct uvc_descriptor_header
*)&target_hdr
->desc
;
544 mutex_unlock(&opts
->lock
);
546 mutex_unlock(su_mutex
);
550 static void uvcg_control_class_drop_link(struct config_item
*src
,
551 struct config_item
*target
)
553 struct config_item
*control
, *header
;
554 struct f_uvc_opts
*opts
;
555 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
556 struct uvc_descriptor_header
**class_array
;
557 struct uvcg_control_header
*target_hdr
;
559 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
561 control
= src
->ci_parent
->ci_parent
;
562 header
= config_group_find_item(to_config_group(control
), "header");
563 if (!header
|| target
->ci_parent
!= header
)
566 opts
= to_f_uvc_opts(control
->ci_parent
);
568 mutex_lock(&opts
->lock
);
570 class_array
= uvcg_get_ctl_class_arr(src
, opts
);
571 if (!class_array
|| opts
->refcnt
)
574 target_hdr
= to_uvcg_control_header(target
);
575 --target_hdr
->linked
;
576 class_array
[0] = NULL
;
579 mutex_unlock(&opts
->lock
);
581 mutex_unlock(su_mutex
);
584 static struct configfs_item_operations uvcg_control_class_item_ops
= {
585 .allow_link
= uvcg_control_class_allow_link
,
586 .drop_link
= uvcg_control_class_drop_link
,
589 static struct config_item_type uvcg_control_class_type
= {
590 .ct_item_ops
= &uvcg_control_class_item_ops
,
591 .ct_owner
= THIS_MODULE
,
595 static struct uvcg_control_class_grp
{
596 struct config_group group
;
597 } uvcg_control_class_grp
;
599 static struct config_item_type uvcg_control_class_grp_type
= {
600 .ct_owner
= THIS_MODULE
,
604 static struct uvcg_control_grp
{
605 struct config_group group
;
608 static struct config_item_type uvcg_control_grp_type
= {
609 .ct_owner
= THIS_MODULE
,
612 /* streaming/uncompressed */
613 static struct uvcg_uncompressed_grp
{
614 struct config_group group
;
615 } uvcg_uncompressed_grp
;
617 /* streaming/mjpeg */
618 static struct uvcg_mjpeg_grp
{
619 struct config_group group
;
622 static struct config_item
*fmt_parent
[] = {
623 &uvcg_uncompressed_grp
.group
.cg_item
,
624 &uvcg_mjpeg_grp
.group
.cg_item
,
627 enum uvcg_format_type
{
628 UVCG_UNCOMPRESSED
= 0,
633 struct config_group group
;
634 enum uvcg_format_type type
;
637 __u8 bmaControls
[UVCG_STREAMING_CONTROL_SIZE
];
640 static struct uvcg_format
*to_uvcg_format(struct config_item
*item
)
642 return container_of(to_config_group(item
), struct uvcg_format
, group
);
645 static ssize_t
uvcg_format_bma_controls_show(struct uvcg_format
*f
, char *page
)
647 struct f_uvc_opts
*opts
;
648 struct config_item
*opts_item
;
649 struct mutex
*su_mutex
= &f
->group
.cg_subsys
->su_mutex
;
653 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
655 opts_item
= f
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
656 opts
= to_f_uvc_opts(opts_item
);
658 mutex_lock(&opts
->lock
);
659 result
= sprintf(pg
, "0x");
661 for (i
= 0; i
< UVCG_STREAMING_CONTROL_SIZE
; ++i
) {
662 result
+= sprintf(pg
, "%x\n", f
->bmaControls
[i
]);
665 mutex_unlock(&opts
->lock
);
667 mutex_unlock(su_mutex
);
671 static ssize_t
uvcg_format_bma_controls_store(struct uvcg_format
*ch
,
672 const char *page
, size_t len
)
674 struct f_uvc_opts
*opts
;
675 struct config_item
*opts_item
;
676 struct mutex
*su_mutex
= &ch
->group
.cg_subsys
->su_mutex
;
679 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
681 opts_item
= ch
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
682 opts
= to_f_uvc_opts(opts_item
);
684 mutex_lock(&opts
->lock
);
685 if (ch
->linked
|| opts
->refcnt
) {
690 if (len
< 4 || *page
!= '0' ||
691 (*(page
+ 1) != 'x' && *(page
+ 1) != 'X'))
693 ret
= hex2bin(ch
->bmaControls
, page
+ 2, 1);
698 mutex_unlock(&opts
->lock
);
699 mutex_unlock(su_mutex
);
703 struct uvcg_format_ptr
{
704 struct uvcg_format
*fmt
;
705 struct list_head entry
;
708 /* streaming/header/<NAME> */
709 struct uvcg_streaming_header
{
710 struct config_item item
;
711 struct uvc_input_header_descriptor desc
;
713 struct list_head formats
;
717 static struct uvcg_streaming_header
*to_uvcg_streaming_header(struct config_item
*item
)
719 return container_of(item
, struct uvcg_streaming_header
, item
);
722 static int uvcg_streaming_header_allow_link(struct config_item
*src
,
723 struct config_item
*target
)
725 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
726 struct config_item
*opts_item
;
727 struct f_uvc_opts
*opts
;
728 struct uvcg_streaming_header
*src_hdr
;
729 struct uvcg_format
*target_fmt
= NULL
;
730 struct uvcg_format_ptr
*format_ptr
;
731 int i
, ret
= -EINVAL
;
733 src_hdr
= to_uvcg_streaming_header(src
);
734 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
736 opts_item
= src
->ci_parent
->ci_parent
->ci_parent
;
737 opts
= to_f_uvc_opts(opts_item
);
739 mutex_lock(&opts
->lock
);
741 if (src_hdr
->linked
) {
746 for (i
= 0; i
< ARRAY_SIZE(fmt_parent
); ++i
)
747 if (target
->ci_parent
== fmt_parent
[i
])
749 if (i
== ARRAY_SIZE(fmt_parent
))
752 target_fmt
= container_of(to_config_group(target
), struct uvcg_format
,
757 format_ptr
= kzalloc(sizeof(*format_ptr
), GFP_KERNEL
);
763 format_ptr
->fmt
= target_fmt
;
764 list_add_tail(&format_ptr
->entry
, &src_hdr
->formats
);
768 mutex_unlock(&opts
->lock
);
769 mutex_unlock(su_mutex
);
773 static void uvcg_streaming_header_drop_link(struct config_item
*src
,
774 struct config_item
*target
)
776 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
777 struct config_item
*opts_item
;
778 struct f_uvc_opts
*opts
;
779 struct uvcg_streaming_header
*src_hdr
;
780 struct uvcg_format
*target_fmt
= NULL
;
781 struct uvcg_format_ptr
*format_ptr
, *tmp
;
783 src_hdr
= to_uvcg_streaming_header(src
);
784 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
786 opts_item
= src
->ci_parent
->ci_parent
->ci_parent
;
787 opts
= to_f_uvc_opts(opts_item
);
789 mutex_lock(&opts
->lock
);
790 target_fmt
= container_of(to_config_group(target
), struct uvcg_format
,
795 list_for_each_entry_safe(format_ptr
, tmp
, &src_hdr
->formats
, entry
)
796 if (format_ptr
->fmt
== target_fmt
) {
797 list_del(&format_ptr
->entry
);
804 mutex_unlock(&opts
->lock
);
805 mutex_unlock(su_mutex
);
808 static struct configfs_item_operations uvcg_streaming_header_item_ops
= {
809 .allow_link
= uvcg_streaming_header_allow_link
,
810 .drop_link
= uvcg_streaming_header_drop_link
,
813 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
814 static ssize_t uvcg_streaming_header_##cname##_show( \
815 struct config_item *item, char *page) \
817 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
818 struct f_uvc_opts *opts; \
819 struct config_item *opts_item; \
820 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
823 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
825 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
826 opts = to_f_uvc_opts(opts_item); \
828 mutex_lock(&opts->lock); \
829 result = sprintf(page, "%d\n", conv(sh->desc.aname)); \
830 mutex_unlock(&opts->lock); \
832 mutex_unlock(su_mutex); \
836 UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
838 #define identity_conv(x) (x)
840 UVCG_STREAMING_HEADER_ATTR(bm_info
, bmInfo
, identity_conv
);
841 UVCG_STREAMING_HEADER_ATTR(b_terminal_link
, bTerminalLink
, identity_conv
);
842 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method
, bStillCaptureMethod
,
844 UVCG_STREAMING_HEADER_ATTR(b_trigger_support
, bTriggerSupport
, identity_conv
);
845 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage
, bTriggerUsage
, identity_conv
);
849 #undef UVCG_STREAMING_HEADER_ATTR
851 static struct configfs_attribute
*uvcg_streaming_header_attrs
[] = {
852 &uvcg_streaming_header_attr_bm_info
,
853 &uvcg_streaming_header_attr_b_terminal_link
,
854 &uvcg_streaming_header_attr_b_still_capture_method
,
855 &uvcg_streaming_header_attr_b_trigger_support
,
856 &uvcg_streaming_header_attr_b_trigger_usage
,
860 static struct config_item_type uvcg_streaming_header_type
= {
861 .ct_item_ops
= &uvcg_streaming_header_item_ops
,
862 .ct_attrs
= uvcg_streaming_header_attrs
,
863 .ct_owner
= THIS_MODULE
,
866 static struct config_item
867 *uvcg_streaming_header_make(struct config_group
*group
, const char *name
)
869 struct uvcg_streaming_header
*h
;
871 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
873 return ERR_PTR(-ENOMEM
);
875 INIT_LIST_HEAD(&h
->formats
);
876 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
877 h
->desc
.bDescriptorSubType
= UVC_VS_INPUT_HEADER
;
878 h
->desc
.bTerminalLink
= 3;
879 h
->desc
.bControlSize
= UVCG_STREAMING_CONTROL_SIZE
;
881 config_item_init_type_name(&h
->item
, name
, &uvcg_streaming_header_type
);
886 static void uvcg_streaming_header_drop(struct config_group
*group
,
887 struct config_item
*item
)
889 struct uvcg_streaming_header
*h
= to_uvcg_streaming_header(item
);
894 /* streaming/header */
895 static struct uvcg_streaming_header_grp
{
896 struct config_group group
;
897 } uvcg_streaming_header_grp
;
899 static struct configfs_group_operations uvcg_streaming_header_grp_ops
= {
900 .make_item
= uvcg_streaming_header_make
,
901 .drop_item
= uvcg_streaming_header_drop
,
904 static struct config_item_type uvcg_streaming_header_grp_type
= {
905 .ct_group_ops
= &uvcg_streaming_header_grp_ops
,
906 .ct_owner
= THIS_MODULE
,
909 /* streaming/<mode>/<format>/<NAME> */
913 u8 b_descriptor_type
;
914 u8 b_descriptor_subtype
;
921 u32 dw_max_video_frame_buffer_size
;
922 u32 dw_default_frame_interval
;
923 u8 b_frame_interval_type
;
924 } __attribute__((packed
)) frame
;
925 u32
*dw_frame_interval
;
926 enum uvcg_format_type fmt_type
;
927 struct config_item item
;
930 static struct uvcg_frame
*to_uvcg_frame(struct config_item
*item
)
932 return container_of(item
, struct uvcg_frame
, item
);
935 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
936 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
938 struct uvcg_frame *f = to_uvcg_frame(item); \
939 struct f_uvc_opts *opts; \
940 struct config_item *opts_item; \
941 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
944 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
946 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
947 opts = to_f_uvc_opts(opts_item); \
949 mutex_lock(&opts->lock); \
950 result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \
951 mutex_unlock(&opts->lock); \
953 mutex_unlock(su_mutex); \
957 static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
958 const char *page, size_t len)\
960 struct uvcg_frame *f = to_uvcg_frame(item); \
961 struct f_uvc_opts *opts; \
962 struct config_item *opts_item; \
963 struct uvcg_format *fmt; \
964 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
968 ret = kstrtou##bits(page, 0, &num); \
972 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
974 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
975 opts = to_f_uvc_opts(opts_item); \
976 fmt = to_uvcg_format(f->item.ci_parent); \
978 mutex_lock(&opts->lock); \
979 if (fmt->linked || opts->refcnt) { \
984 f->frame.cname = to_little_endian(num); \
987 mutex_unlock(&opts->lock); \
988 mutex_unlock(su_mutex); \
992 UVC_ATTR(uvcg_frame_, cname, aname);
994 #define noop_conversion(x) (x)
996 UVCG_FRAME_ATTR(bm_capabilities
, bmCapabilities
, noop_conversion
,
998 UVCG_FRAME_ATTR(w_width
, wWidth
, le16_to_cpu
, cpu_to_le16
, 16);
999 UVCG_FRAME_ATTR(w_height
, wHeight
, le16_to_cpu
, cpu_to_le16
, 16);
1000 UVCG_FRAME_ATTR(dw_min_bit_rate
, dwMinBitRate
, le32_to_cpu
, cpu_to_le32
, 32);
1001 UVCG_FRAME_ATTR(dw_max_bit_rate
, dwMaxBitRate
, le32_to_cpu
, cpu_to_le32
, 32);
1002 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size
, dwMaxVideoFrameBufferSize
,
1003 le32_to_cpu
, cpu_to_le32
, 32);
1004 UVCG_FRAME_ATTR(dw_default_frame_interval
, dwDefaultFrameInterval
,
1005 le32_to_cpu
, cpu_to_le32
, 32);
1007 #undef noop_conversion
1009 #undef UVCG_FRAME_ATTR
1011 static ssize_t
uvcg_frame_dw_frame_interval_show(struct config_item
*item
,
1014 struct uvcg_frame
*frm
= to_uvcg_frame(item
);
1015 struct f_uvc_opts
*opts
;
1016 struct config_item
*opts_item
;
1017 struct mutex
*su_mutex
= &frm
->item
.ci_group
->cg_subsys
->su_mutex
;
1021 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1023 opts_item
= frm
->item
.ci_parent
->ci_parent
->ci_parent
->ci_parent
;
1024 opts
= to_f_uvc_opts(opts_item
);
1026 mutex_lock(&opts
->lock
);
1027 for (result
= 0, i
= 0; i
< frm
->frame
.b_frame_interval_type
; ++i
) {
1028 result
+= sprintf(pg
, "%d\n",
1029 le32_to_cpu(frm
->dw_frame_interval
[i
]));
1032 mutex_unlock(&opts
->lock
);
1034 mutex_unlock(su_mutex
);
1038 static inline int __uvcg_count_frm_intrv(char *buf
, void *priv
)
1044 static inline int __uvcg_fill_frm_intrv(char *buf
, void *priv
)
1049 ret
= kstrtou32(buf
, 0, &num
);
1054 **interv
= cpu_to_le32(num
);
1060 static int __uvcg_iter_frm_intrv(const char *page
, size_t len
,
1061 int (*fun
)(char *, void *), void *priv
)
1063 /* sign, base 2 representation, newline, terminator */
1064 char buf
[1 + sizeof(u32
) * 8 + 1 + 1];
1065 const char *pg
= page
;
1071 while (pg
- page
< len
) {
1073 while (i
< sizeof(buf
) && (pg
- page
< len
) &&
1074 *pg
!= '\0' && *pg
!= '\n')
1076 if (i
== sizeof(buf
))
1078 while ((pg
- page
< len
) && (*pg
== '\0' || *pg
== '\n'))
1081 ret
= fun(buf
, priv
);
1089 static ssize_t
uvcg_frame_dw_frame_interval_store(struct config_item
*item
,
1090 const char *page
, size_t len
)
1092 struct uvcg_frame
*ch
= to_uvcg_frame(item
);
1093 struct f_uvc_opts
*opts
;
1094 struct config_item
*opts_item
;
1095 struct uvcg_format
*fmt
;
1096 struct mutex
*su_mutex
= &ch
->item
.ci_group
->cg_subsys
->su_mutex
;
1098 u32
*frm_intrv
, *tmp
;
1100 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1102 opts_item
= ch
->item
.ci_parent
->ci_parent
->ci_parent
->ci_parent
;
1103 opts
= to_f_uvc_opts(opts_item
);
1104 fmt
= to_uvcg_format(ch
->item
.ci_parent
);
1106 mutex_lock(&opts
->lock
);
1107 if (fmt
->linked
|| opts
->refcnt
) {
1112 ret
= __uvcg_iter_frm_intrv(page
, len
, __uvcg_count_frm_intrv
, &n
);
1116 tmp
= frm_intrv
= kcalloc(n
, sizeof(u32
), GFP_KERNEL
);
1122 ret
= __uvcg_iter_frm_intrv(page
, len
, __uvcg_fill_frm_intrv
, &tmp
);
1128 kfree(ch
->dw_frame_interval
);
1129 ch
->dw_frame_interval
= frm_intrv
;
1130 ch
->frame
.b_frame_interval_type
= n
;
1134 mutex_unlock(&opts
->lock
);
1135 mutex_unlock(su_mutex
);
1139 UVC_ATTR(uvcg_frame_
, dw_frame_interval
, dwFrameInterval
);
1141 static struct configfs_attribute
*uvcg_frame_attrs
[] = {
1142 &uvcg_frame_attr_bm_capabilities
,
1143 &uvcg_frame_attr_w_width
,
1144 &uvcg_frame_attr_w_height
,
1145 &uvcg_frame_attr_dw_min_bit_rate
,
1146 &uvcg_frame_attr_dw_max_bit_rate
,
1147 &uvcg_frame_attr_dw_max_video_frame_buffer_size
,
1148 &uvcg_frame_attr_dw_default_frame_interval
,
1149 &uvcg_frame_attr_dw_frame_interval
,
1153 static struct config_item_type uvcg_frame_type
= {
1154 .ct_attrs
= uvcg_frame_attrs
,
1155 .ct_owner
= THIS_MODULE
,
1158 static struct config_item
*uvcg_frame_make(struct config_group
*group
,
1161 struct uvcg_frame
*h
;
1162 struct uvcg_format
*fmt
;
1163 struct f_uvc_opts
*opts
;
1164 struct config_item
*opts_item
;
1166 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1168 return ERR_PTR(-ENOMEM
);
1170 h
->frame
.b_descriptor_type
= USB_DT_CS_INTERFACE
;
1171 h
->frame
.b_frame_index
= 1;
1172 h
->frame
.w_width
= cpu_to_le16(640);
1173 h
->frame
.w_height
= cpu_to_le16(360);
1174 h
->frame
.dw_min_bit_rate
= cpu_to_le32(18432000);
1175 h
->frame
.dw_max_bit_rate
= cpu_to_le32(55296000);
1176 h
->frame
.dw_max_video_frame_buffer_size
= cpu_to_le32(460800);
1177 h
->frame
.dw_default_frame_interval
= cpu_to_le32(666666);
1179 opts_item
= group
->cg_item
.ci_parent
->ci_parent
->ci_parent
;
1180 opts
= to_f_uvc_opts(opts_item
);
1182 mutex_lock(&opts
->lock
);
1183 fmt
= to_uvcg_format(&group
->cg_item
);
1184 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1185 h
->frame
.b_descriptor_subtype
= UVC_VS_FRAME_UNCOMPRESSED
;
1186 h
->fmt_type
= UVCG_UNCOMPRESSED
;
1187 } else if (fmt
->type
== UVCG_MJPEG
) {
1188 h
->frame
.b_descriptor_subtype
= UVC_VS_FRAME_MJPEG
;
1189 h
->fmt_type
= UVCG_MJPEG
;
1191 mutex_unlock(&opts
->lock
);
1193 return ERR_PTR(-EINVAL
);
1196 mutex_unlock(&opts
->lock
);
1198 config_item_init_type_name(&h
->item
, name
, &uvcg_frame_type
);
1203 static void uvcg_frame_drop(struct config_group
*group
, struct config_item
*item
)
1205 struct uvcg_frame
*h
= to_uvcg_frame(item
);
1206 struct uvcg_format
*fmt
;
1207 struct f_uvc_opts
*opts
;
1208 struct config_item
*opts_item
;
1210 opts_item
= group
->cg_item
.ci_parent
->ci_parent
->ci_parent
;
1211 opts
= to_f_uvc_opts(opts_item
);
1213 mutex_lock(&opts
->lock
);
1214 fmt
= to_uvcg_format(&group
->cg_item
);
1217 mutex_unlock(&opts
->lock
);
1220 /* streaming/uncompressed/<NAME> */
1221 struct uvcg_uncompressed
{
1222 struct uvcg_format fmt
;
1223 struct uvc_format_uncompressed desc
;
1226 static struct uvcg_uncompressed
*to_uvcg_uncompressed(struct config_item
*item
)
1228 return container_of(
1229 container_of(to_config_group(item
), struct uvcg_format
, group
),
1230 struct uvcg_uncompressed
, fmt
);
1233 static struct configfs_group_operations uvcg_uncompressed_group_ops
= {
1234 .make_item
= uvcg_frame_make
,
1235 .drop_item
= uvcg_frame_drop
,
1238 static ssize_t
uvcg_uncompressed_guid_format_show(struct config_item
*item
,
1241 struct uvcg_uncompressed
*ch
= to_uvcg_uncompressed(item
);
1242 struct f_uvc_opts
*opts
;
1243 struct config_item
*opts_item
;
1244 struct mutex
*su_mutex
= &ch
->fmt
.group
.cg_subsys
->su_mutex
;
1246 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1248 opts_item
= ch
->fmt
.group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
1249 opts
= to_f_uvc_opts(opts_item
);
1251 mutex_lock(&opts
->lock
);
1252 memcpy(page
, ch
->desc
.guidFormat
, sizeof(ch
->desc
.guidFormat
));
1253 mutex_unlock(&opts
->lock
);
1255 mutex_unlock(su_mutex
);
1257 return sizeof(ch
->desc
.guidFormat
);
1260 static ssize_t
uvcg_uncompressed_guid_format_store(struct config_item
*item
,
1261 const char *page
, size_t len
)
1263 struct uvcg_uncompressed
*ch
= to_uvcg_uncompressed(item
);
1264 struct f_uvc_opts
*opts
;
1265 struct config_item
*opts_item
;
1266 struct mutex
*su_mutex
= &ch
->fmt
.group
.cg_subsys
->su_mutex
;
1269 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1271 opts_item
= ch
->fmt
.group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
1272 opts
= to_f_uvc_opts(opts_item
);
1274 mutex_lock(&opts
->lock
);
1275 if (ch
->fmt
.linked
|| opts
->refcnt
) {
1280 memcpy(ch
->desc
.guidFormat
, page
,
1281 min(sizeof(ch
->desc
.guidFormat
), len
));
1282 ret
= sizeof(ch
->desc
.guidFormat
);
1285 mutex_unlock(&opts
->lock
);
1286 mutex_unlock(su_mutex
);
1290 UVC_ATTR(uvcg_uncompressed_
, guid_format
, guidFormat
);
1292 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
1293 static ssize_t uvcg_uncompressed_##cname##_show( \
1294 struct config_item *item, char *page) \
1296 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1297 struct f_uvc_opts *opts; \
1298 struct config_item *opts_item; \
1299 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1302 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1304 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1305 opts = to_f_uvc_opts(opts_item); \
1307 mutex_lock(&opts->lock); \
1308 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1309 mutex_unlock(&opts->lock); \
1311 mutex_unlock(su_mutex); \
1315 UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
1317 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
1318 static ssize_t uvcg_uncompressed_##cname##_show( \
1319 struct config_item *item, char *page) \
1321 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1322 struct f_uvc_opts *opts; \
1323 struct config_item *opts_item; \
1324 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1327 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1329 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1330 opts = to_f_uvc_opts(opts_item); \
1332 mutex_lock(&opts->lock); \
1333 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1334 mutex_unlock(&opts->lock); \
1336 mutex_unlock(su_mutex); \
1341 uvcg_uncompressed_##cname##_store(struct config_item *item, \
1342 const char *page, size_t len) \
1344 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1345 struct f_uvc_opts *opts; \
1346 struct config_item *opts_item; \
1347 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1351 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1353 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1354 opts = to_f_uvc_opts(opts_item); \
1356 mutex_lock(&opts->lock); \
1357 if (u->fmt.linked || opts->refcnt) { \
1362 ret = kstrtou8(page, 0, &num); \
1370 u->desc.aname = num; \
1373 mutex_unlock(&opts->lock); \
1374 mutex_unlock(su_mutex); \
1378 UVC_ATTR(uvcg_uncompressed_, cname, aname);
1380 #define identity_conv(x) (x)
1382 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel
, bBitsPerPixel
, identity_conv
);
1383 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index
, bDefaultFrameIndex
,
1385 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x
, bAspectRatioX
, identity_conv
);
1386 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y
, bAspectRatioY
, identity_conv
);
1387 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags
, bmInterfaceFlags
, identity_conv
);
1389 #undef identity_conv
1391 #undef UVCG_UNCOMPRESSED_ATTR
1392 #undef UVCG_UNCOMPRESSED_ATTR_RO
1394 static inline ssize_t
1395 uvcg_uncompressed_bma_controls_show(struct config_item
*item
, char *page
)
1397 struct uvcg_uncompressed
*unc
= to_uvcg_uncompressed(item
);
1398 return uvcg_format_bma_controls_show(&unc
->fmt
, page
);
1401 static inline ssize_t
1402 uvcg_uncompressed_bma_controls_store(struct config_item
*item
,
1403 const char *page
, size_t len
)
1405 struct uvcg_uncompressed
*unc
= to_uvcg_uncompressed(item
);
1406 return uvcg_format_bma_controls_store(&unc
->fmt
, page
, len
);
1409 UVC_ATTR(uvcg_uncompressed_
, bma_controls
, bmaControls
);
1411 static struct configfs_attribute
*uvcg_uncompressed_attrs
[] = {
1412 &uvcg_uncompressed_attr_guid_format
,
1413 &uvcg_uncompressed_attr_b_bits_per_pixel
,
1414 &uvcg_uncompressed_attr_b_default_frame_index
,
1415 &uvcg_uncompressed_attr_b_aspect_ratio_x
,
1416 &uvcg_uncompressed_attr_b_aspect_ratio_y
,
1417 &uvcg_uncompressed_attr_bm_interface_flags
,
1418 &uvcg_uncompressed_attr_bma_controls
,
1422 static struct config_item_type uvcg_uncompressed_type
= {
1423 .ct_group_ops
= &uvcg_uncompressed_group_ops
,
1424 .ct_attrs
= uvcg_uncompressed_attrs
,
1425 .ct_owner
= THIS_MODULE
,
1428 static struct config_group
*uvcg_uncompressed_make(struct config_group
*group
,
1431 static char guid
[] = {
1432 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
1433 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1435 struct uvcg_uncompressed
*h
;
1437 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1439 return ERR_PTR(-ENOMEM
);
1441 h
->desc
.bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
;
1442 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
1443 h
->desc
.bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
;
1444 memcpy(h
->desc
.guidFormat
, guid
, sizeof(guid
));
1445 h
->desc
.bBitsPerPixel
= 16;
1446 h
->desc
.bDefaultFrameIndex
= 1;
1447 h
->desc
.bAspectRatioX
= 0;
1448 h
->desc
.bAspectRatioY
= 0;
1449 h
->desc
.bmInterfaceFlags
= 0;
1450 h
->desc
.bCopyProtect
= 0;
1452 h
->fmt
.type
= UVCG_UNCOMPRESSED
;
1453 config_group_init_type_name(&h
->fmt
.group
, name
,
1454 &uvcg_uncompressed_type
);
1456 return &h
->fmt
.group
;
1459 static void uvcg_uncompressed_drop(struct config_group
*group
,
1460 struct config_item
*item
)
1462 struct uvcg_uncompressed
*h
= to_uvcg_uncompressed(item
);
1467 static struct configfs_group_operations uvcg_uncompressed_grp_ops
= {
1468 .make_group
= uvcg_uncompressed_make
,
1469 .drop_item
= uvcg_uncompressed_drop
,
1472 static struct config_item_type uvcg_uncompressed_grp_type
= {
1473 .ct_group_ops
= &uvcg_uncompressed_grp_ops
,
1474 .ct_owner
= THIS_MODULE
,
1477 /* streaming/mjpeg/<NAME> */
1479 struct uvcg_format fmt
;
1480 struct uvc_format_mjpeg desc
;
1483 static struct uvcg_mjpeg
*to_uvcg_mjpeg(struct config_item
*item
)
1485 return container_of(
1486 container_of(to_config_group(item
), struct uvcg_format
, group
),
1487 struct uvcg_mjpeg
, fmt
);
1490 static struct configfs_group_operations uvcg_mjpeg_group_ops
= {
1491 .make_item
= uvcg_frame_make
,
1492 .drop_item
= uvcg_frame_drop
,
1495 #define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
1496 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1498 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1499 struct f_uvc_opts *opts; \
1500 struct config_item *opts_item; \
1501 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1504 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1506 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1507 opts = to_f_uvc_opts(opts_item); \
1509 mutex_lock(&opts->lock); \
1510 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1511 mutex_unlock(&opts->lock); \
1513 mutex_unlock(su_mutex); \
1517 UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
1519 #define UVCG_MJPEG_ATTR(cname, aname, conv) \
1520 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1522 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1523 struct f_uvc_opts *opts; \
1524 struct config_item *opts_item; \
1525 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1528 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1530 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1531 opts = to_f_uvc_opts(opts_item); \
1533 mutex_lock(&opts->lock); \
1534 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1535 mutex_unlock(&opts->lock); \
1537 mutex_unlock(su_mutex); \
1542 uvcg_mjpeg_##cname##_store(struct config_item *item, \
1543 const char *page, size_t len) \
1545 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1546 struct f_uvc_opts *opts; \
1547 struct config_item *opts_item; \
1548 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1552 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1554 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1555 opts = to_f_uvc_opts(opts_item); \
1557 mutex_lock(&opts->lock); \
1558 if (u->fmt.linked || opts->refcnt) { \
1563 ret = kstrtou8(page, 0, &num); \
1571 u->desc.aname = num; \
1574 mutex_unlock(&opts->lock); \
1575 mutex_unlock(su_mutex); \
1579 UVC_ATTR(uvcg_mjpeg_, cname, aname)
1581 #define identity_conv(x) (x)
1583 UVCG_MJPEG_ATTR(b_default_frame_index
, bDefaultFrameIndex
,
1585 UVCG_MJPEG_ATTR_RO(bm_flags
, bmFlags
, identity_conv
);
1586 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x
, bAspectRatioX
, identity_conv
);
1587 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y
, bAspectRatioY
, identity_conv
);
1588 UVCG_MJPEG_ATTR_RO(bm_interface_flags
, bmInterfaceFlags
, identity_conv
);
1590 #undef identity_conv
1592 #undef UVCG_MJPEG_ATTR
1593 #undef UVCG_MJPEG_ATTR_RO
1595 static inline ssize_t
1596 uvcg_mjpeg_bma_controls_show(struct config_item
*item
, char *page
)
1598 struct uvcg_mjpeg
*u
= to_uvcg_mjpeg(item
);
1599 return uvcg_format_bma_controls_show(&u
->fmt
, page
);
1602 static inline ssize_t
1603 uvcg_mjpeg_bma_controls_store(struct config_item
*item
,
1604 const char *page
, size_t len
)
1606 struct uvcg_mjpeg
*u
= to_uvcg_mjpeg(item
);
1607 return uvcg_format_bma_controls_store(&u
->fmt
, page
, len
);
1610 UVC_ATTR(uvcg_mjpeg_
, bma_controls
, bmaControls
);
1612 static struct configfs_attribute
*uvcg_mjpeg_attrs
[] = {
1613 &uvcg_mjpeg_attr_b_default_frame_index
,
1614 &uvcg_mjpeg_attr_bm_flags
,
1615 &uvcg_mjpeg_attr_b_aspect_ratio_x
,
1616 &uvcg_mjpeg_attr_b_aspect_ratio_y
,
1617 &uvcg_mjpeg_attr_bm_interface_flags
,
1618 &uvcg_mjpeg_attr_bma_controls
,
1622 static struct config_item_type uvcg_mjpeg_type
= {
1623 .ct_group_ops
= &uvcg_mjpeg_group_ops
,
1624 .ct_attrs
= uvcg_mjpeg_attrs
,
1625 .ct_owner
= THIS_MODULE
,
1628 static struct config_group
*uvcg_mjpeg_make(struct config_group
*group
,
1631 struct uvcg_mjpeg
*h
;
1633 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1635 return ERR_PTR(-ENOMEM
);
1637 h
->desc
.bLength
= UVC_DT_FORMAT_MJPEG_SIZE
;
1638 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
1639 h
->desc
.bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
;
1640 h
->desc
.bDefaultFrameIndex
= 1;
1641 h
->desc
.bAspectRatioX
= 0;
1642 h
->desc
.bAspectRatioY
= 0;
1643 h
->desc
.bmInterfaceFlags
= 0;
1644 h
->desc
.bCopyProtect
= 0;
1646 h
->fmt
.type
= UVCG_MJPEG
;
1647 config_group_init_type_name(&h
->fmt
.group
, name
,
1650 return &h
->fmt
.group
;
1653 static void uvcg_mjpeg_drop(struct config_group
*group
,
1654 struct config_item
*item
)
1656 struct uvcg_mjpeg
*h
= to_uvcg_mjpeg(item
);
1661 static struct configfs_group_operations uvcg_mjpeg_grp_ops
= {
1662 .make_group
= uvcg_mjpeg_make
,
1663 .drop_item
= uvcg_mjpeg_drop
,
1666 static struct config_item_type uvcg_mjpeg_grp_type
= {
1667 .ct_group_ops
= &uvcg_mjpeg_grp_ops
,
1668 .ct_owner
= THIS_MODULE
,
1671 /* streaming/color_matching/default */
1672 static struct uvcg_default_color_matching
{
1673 struct config_group group
;
1674 } uvcg_default_color_matching
;
1676 static inline struct uvcg_default_color_matching
1677 *to_uvcg_default_color_matching(struct config_item
*item
)
1679 return container_of(to_config_group(item
),
1680 struct uvcg_default_color_matching
, group
);
1683 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
1684 static ssize_t uvcg_default_color_matching_##cname##_show( \
1685 struct config_item *item, char *page) \
1687 struct uvcg_default_color_matching *dc = \
1688 to_uvcg_default_color_matching(item); \
1689 struct f_uvc_opts *opts; \
1690 struct config_item *opts_item; \
1691 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
1692 struct uvc_color_matching_descriptor *cd; \
1695 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1697 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \
1698 opts = to_f_uvc_opts(opts_item); \
1699 cd = &opts->uvc_color_matching; \
1701 mutex_lock(&opts->lock); \
1702 result = sprintf(page, "%d\n", conv(cd->aname)); \
1703 mutex_unlock(&opts->lock); \
1705 mutex_unlock(su_mutex); \
1709 UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
1711 #define identity_conv(x) (x)
1713 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries
, bColorPrimaries
,
1715 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics
,
1716 bTransferCharacteristics
, identity_conv
);
1717 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients
, bMatrixCoefficients
,
1720 #undef identity_conv
1722 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1724 static struct configfs_attribute
*uvcg_default_color_matching_attrs
[] = {
1725 &uvcg_default_color_matching_attr_b_color_primaries
,
1726 &uvcg_default_color_matching_attr_b_transfer_characteristics
,
1727 &uvcg_default_color_matching_attr_b_matrix_coefficients
,
1731 static struct config_item_type uvcg_default_color_matching_type
= {
1732 .ct_attrs
= uvcg_default_color_matching_attrs
,
1733 .ct_owner
= THIS_MODULE
,
1736 /* struct uvcg_color_matching {}; */
1738 /* streaming/color_matching */
1739 static struct uvcg_color_matching_grp
{
1740 struct config_group group
;
1741 } uvcg_color_matching_grp
;
1743 static struct config_item_type uvcg_color_matching_grp_type
= {
1744 .ct_owner
= THIS_MODULE
,
1747 /* streaming/class/{fs|hs|ss} */
1748 static struct uvcg_streaming_class
{
1749 struct config_group group
;
1750 } uvcg_streaming_class_fs
, uvcg_streaming_class_hs
, uvcg_streaming_class_ss
;
1753 static inline struct uvc_descriptor_header
1754 ***__uvcg_get_stream_class_arr(struct config_item
*i
, struct f_uvc_opts
*o
)
1756 struct uvcg_streaming_class
*cl
= container_of(to_config_group(i
),
1757 struct uvcg_streaming_class
, group
);
1759 if (cl
== &uvcg_streaming_class_fs
)
1760 return &o
->uvc_fs_streaming_cls
;
1762 if (cl
== &uvcg_streaming_class_hs
)
1763 return &o
->uvc_hs_streaming_cls
;
1765 if (cl
== &uvcg_streaming_class_ss
)
1766 return &o
->uvc_ss_streaming_cls
;
1771 enum uvcg_strm_type
{
1778 * Iterate over a hierarchy of streaming descriptors' config items.
1779 * The items are created by the user with configfs.
1781 * It "processes" the header pointed to by @priv1, then for each format
1782 * that follows the header "processes" the format itself and then for
1783 * each frame inside a format "processes" the frame.
1785 * As a "processing" function the @fun is used.
1787 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
1788 * the amount of memory needed for an array of streaming descriptors
1789 * and second, to actually fill the array.
1791 * @h: streaming header pointer
1792 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
1793 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
1794 * @fun: callback function for processing each level of the hierarchy
1796 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header
*h
,
1797 void *priv2
, void *priv3
,
1798 int (*fun
)(void *, void *, void *, int, enum uvcg_strm_type type
))
1800 struct uvcg_format_ptr
*f
;
1801 struct config_group
*grp
;
1802 struct config_item
*item
;
1803 struct uvcg_frame
*frm
;
1810 ret
= fun(h
, priv2
, priv3
, 0, UVCG_HEADER
);
1813 list_for_each_entry(f
, &h
->formats
, entry
) {
1814 ret
= fun(f
->fmt
, priv2
, priv3
, i
++, UVCG_FORMAT
);
1817 grp
= &f
->fmt
->group
;
1818 list_for_each_entry(item
, &grp
->cg_children
, ci_entry
) {
1819 frm
= to_uvcg_frame(item
);
1820 ret
= fun(frm
, priv2
, priv3
, j
++, UVCG_FRAME
);
1830 * Count how many bytes are needed for an array of streaming descriptors.
1832 * @priv1: pointer to a header, format or frame
1833 * @priv2: inout parameter, accumulated size of the array
1834 * @priv3: inout parameter, accumulated number of the array elements
1835 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
1837 static int __uvcg_cnt_strm(void *priv1
, void *priv2
, void *priv3
, int n
,
1838 enum uvcg_strm_type type
)
1840 size_t *size
= priv2
;
1841 size_t *count
= priv3
;
1845 struct uvcg_streaming_header
*h
= priv1
;
1847 *size
+= sizeof(h
->desc
);
1849 *size
+= h
->num_fmt
* UVCG_STREAMING_CONTROL_SIZE
;
1853 struct uvcg_format
*fmt
= priv1
;
1855 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1856 struct uvcg_uncompressed
*u
=
1857 container_of(fmt
, struct uvcg_uncompressed
,
1860 *size
+= sizeof(u
->desc
);
1861 } else if (fmt
->type
== UVCG_MJPEG
) {
1862 struct uvcg_mjpeg
*m
=
1863 container_of(fmt
, struct uvcg_mjpeg
, fmt
);
1865 *size
+= sizeof(m
->desc
);
1872 struct uvcg_frame
*frm
= priv1
;
1873 int sz
= sizeof(frm
->dw_frame_interval
);
1875 *size
+= sizeof(frm
->frame
);
1876 *size
+= frm
->frame
.b_frame_interval_type
* sz
;
1887 * Fill an array of streaming descriptors.
1889 * @priv1: pointer to a header, format or frame
1890 * @priv2: inout parameter, pointer into a block of memory
1891 * @priv3: inout parameter, pointer to a 2-dimensional array
1893 static int __uvcg_fill_strm(void *priv1
, void *priv2
, void *priv3
, int n
,
1894 enum uvcg_strm_type type
)
1896 void **dest
= priv2
;
1897 struct uvc_descriptor_header
***array
= priv3
;
1905 struct uvc_input_header_descriptor
*ihdr
= *dest
;
1906 struct uvcg_streaming_header
*h
= priv1
;
1907 struct uvcg_format_ptr
*f
;
1909 memcpy(*dest
, &h
->desc
, sizeof(h
->desc
));
1910 *dest
+= sizeof(h
->desc
);
1911 sz
= UVCG_STREAMING_CONTROL_SIZE
;
1912 list_for_each_entry(f
, &h
->formats
, entry
) {
1913 memcpy(*dest
, f
->fmt
->bmaControls
, sz
);
1916 ihdr
->bLength
= sizeof(h
->desc
) + h
->num_fmt
* sz
;
1917 ihdr
->bNumFormats
= h
->num_fmt
;
1921 struct uvcg_format
*fmt
= priv1
;
1923 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1924 struct uvc_format_uncompressed
*unc
= *dest
;
1925 struct uvcg_uncompressed
*u
=
1926 container_of(fmt
, struct uvcg_uncompressed
,
1929 memcpy(*dest
, &u
->desc
, sizeof(u
->desc
));
1930 *dest
+= sizeof(u
->desc
);
1931 unc
->bNumFrameDescriptors
= fmt
->num_frames
;
1932 unc
->bFormatIndex
= n
+ 1;
1933 } else if (fmt
->type
== UVCG_MJPEG
) {
1934 struct uvc_format_mjpeg
*mjp
= *dest
;
1935 struct uvcg_mjpeg
*m
=
1936 container_of(fmt
, struct uvcg_mjpeg
, fmt
);
1938 memcpy(*dest
, &m
->desc
, sizeof(m
->desc
));
1939 *dest
+= sizeof(m
->desc
);
1940 mjp
->bNumFrameDescriptors
= fmt
->num_frames
;
1941 mjp
->bFormatIndex
= n
+ 1;
1948 struct uvcg_frame
*frm
= priv1
;
1949 struct uvc_descriptor_header
*h
= *dest
;
1951 sz
= sizeof(frm
->frame
);
1952 memcpy(*dest
, &frm
->frame
, sz
);
1954 sz
= frm
->frame
.b_frame_interval_type
*
1955 sizeof(*frm
->dw_frame_interval
);
1956 memcpy(*dest
, frm
->dw_frame_interval
, sz
);
1958 if (frm
->fmt_type
== UVCG_UNCOMPRESSED
)
1959 h
->bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(
1960 frm
->frame
.b_frame_interval_type
);
1961 else if (frm
->fmt_type
== UVCG_MJPEG
)
1962 h
->bLength
= UVC_DT_FRAME_MJPEG_SIZE(
1963 frm
->frame
.b_frame_interval_type
);
1971 static int uvcg_streaming_class_allow_link(struct config_item
*src
,
1972 struct config_item
*target
)
1974 struct config_item
*streaming
, *header
;
1975 struct f_uvc_opts
*opts
;
1976 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
1977 struct uvc_descriptor_header
***class_array
, **cl_arr
;
1978 struct uvcg_streaming_header
*target_hdr
;
1979 void *data
, *data_save
;
1980 size_t size
= 0, count
= 0;
1983 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1985 streaming
= src
->ci_parent
->ci_parent
;
1986 header
= config_group_find_item(to_config_group(streaming
), "header");
1987 if (!header
|| target
->ci_parent
!= header
)
1990 opts
= to_f_uvc_opts(streaming
->ci_parent
);
1992 mutex_lock(&opts
->lock
);
1994 class_array
= __uvcg_get_stream_class_arr(src
, opts
);
1995 if (!class_array
|| *class_array
|| opts
->refcnt
) {
2000 target_hdr
= to_uvcg_streaming_header(target
);
2001 ret
= __uvcg_iter_strm_cls(target_hdr
, &size
, &count
, __uvcg_cnt_strm
);
2005 count
+= 2; /* color_matching, NULL */
2006 *class_array
= kcalloc(count
, sizeof(void *), GFP_KERNEL
);
2007 if (!*class_array
) {
2012 data
= data_save
= kzalloc(size
, GFP_KERNEL
);
2014 kfree(*class_array
);
2015 *class_array
= NULL
;
2019 cl_arr
= *class_array
;
2020 ret
= __uvcg_iter_strm_cls(target_hdr
, &data
, &cl_arr
,
2023 kfree(*class_array
);
2024 *class_array
= NULL
;
2026 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2027 * might have advanced the "data", so use a backup copy
2032 *cl_arr
= (struct uvc_descriptor_header
*)&opts
->uvc_color_matching
;
2034 ++target_hdr
->linked
;
2038 mutex_unlock(&opts
->lock
);
2040 mutex_unlock(su_mutex
);
2044 static void uvcg_streaming_class_drop_link(struct config_item
*src
,
2045 struct config_item
*target
)
2047 struct config_item
*streaming
, *header
;
2048 struct f_uvc_opts
*opts
;
2049 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
2050 struct uvc_descriptor_header
***class_array
;
2051 struct uvcg_streaming_header
*target_hdr
;
2053 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
2055 streaming
= src
->ci_parent
->ci_parent
;
2056 header
= config_group_find_item(to_config_group(streaming
), "header");
2057 if (!header
|| target
->ci_parent
!= header
)
2060 opts
= to_f_uvc_opts(streaming
->ci_parent
);
2062 mutex_lock(&opts
->lock
);
2064 class_array
= __uvcg_get_stream_class_arr(src
, opts
);
2065 if (!class_array
|| !*class_array
)
2071 target_hdr
= to_uvcg_streaming_header(target
);
2072 --target_hdr
->linked
;
2073 kfree(**class_array
);
2074 kfree(*class_array
);
2075 *class_array
= NULL
;
2078 mutex_unlock(&opts
->lock
);
2080 mutex_unlock(su_mutex
);
2083 static struct configfs_item_operations uvcg_streaming_class_item_ops
= {
2084 .allow_link
= uvcg_streaming_class_allow_link
,
2085 .drop_link
= uvcg_streaming_class_drop_link
,
2088 static struct config_item_type uvcg_streaming_class_type
= {
2089 .ct_item_ops
= &uvcg_streaming_class_item_ops
,
2090 .ct_owner
= THIS_MODULE
,
2093 /* streaming/class */
2094 static struct uvcg_streaming_class_grp
{
2095 struct config_group group
;
2096 } uvcg_streaming_class_grp
;
2098 static struct config_item_type uvcg_streaming_class_grp_type
= {
2099 .ct_owner
= THIS_MODULE
,
2103 static struct uvcg_streaming_grp
{
2104 struct config_group group
;
2105 } uvcg_streaming_grp
;
2107 static struct config_item_type uvcg_streaming_grp_type
= {
2108 .ct_owner
= THIS_MODULE
,
2111 static inline struct f_uvc_opts
*to_f_uvc_opts(struct config_item
*item
)
2113 return container_of(to_config_group(item
), struct f_uvc_opts
,
2117 static void uvc_attr_release(struct config_item
*item
)
2119 struct f_uvc_opts
*opts
= to_f_uvc_opts(item
);
2121 usb_put_function_instance(&opts
->func_inst
);
2124 static struct configfs_item_operations uvc_item_ops
= {
2125 .release
= uvc_attr_release
,
2128 #define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
2129 static ssize_t f_uvc_opts_##cname##_show( \
2130 struct config_item *item, char *page) \
2132 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2135 mutex_lock(&opts->lock); \
2136 result = sprintf(page, "%d\n", conv(opts->cname)); \
2137 mutex_unlock(&opts->lock); \
2143 f_uvc_opts_##cname##_store(struct config_item *item, \
2144 const char *page, size_t len) \
2146 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2150 mutex_lock(&opts->lock); \
2151 if (opts->refcnt) { \
2156 ret = str2u(page, 0, &num); \
2160 if (num > limit) { \
2164 opts->cname = vnoc(num); \
2167 mutex_unlock(&opts->lock); \
2171 UVC_ATTR(f_uvc_opts_, cname, cname)
2173 #define identity_conv(x) (x)
2175 UVCG_OPTS_ATTR(streaming_interval
, streaming_interval
, identity_conv
,
2176 kstrtou8
, u8
, identity_conv
, 16);
2177 UVCG_OPTS_ATTR(streaming_maxpacket
, streaming_maxpacket
, le16_to_cpu
,
2178 kstrtou16
, u16
, le16_to_cpu
, 3072);
2179 UVCG_OPTS_ATTR(streaming_maxburst
, streaming_maxburst
, identity_conv
,
2180 kstrtou8
, u8
, identity_conv
, 15);
2182 #undef identity_conv
2184 #undef UVCG_OPTS_ATTR
2186 static struct configfs_attribute
*uvc_attrs
[] = {
2187 &f_uvc_opts_attr_streaming_interval
,
2188 &f_uvc_opts_attr_streaming_maxpacket
,
2189 &f_uvc_opts_attr_streaming_maxburst
,
2193 static struct config_item_type uvc_func_type
= {
2194 .ct_item_ops
= &uvc_item_ops
,
2195 .ct_attrs
= uvc_attrs
,
2196 .ct_owner
= THIS_MODULE
,
2199 int uvcg_attach_configfs(struct f_uvc_opts
*opts
)
2201 config_group_init_type_name(&uvcg_control_header_grp
.group
,
2203 &uvcg_control_header_grp_type
);
2205 config_group_init_type_name(&uvcg_default_processing
.group
,
2206 "default", &uvcg_default_processing_type
);
2207 config_group_init_type_name(&uvcg_processing_grp
.group
,
2208 "processing", &uvcg_processing_grp_type
);
2209 configfs_add_default_group(&uvcg_default_processing
.group
,
2210 &uvcg_processing_grp
.group
);
2212 config_group_init_type_name(&uvcg_default_camera
.group
,
2213 "default", &uvcg_default_camera_type
);
2214 config_group_init_type_name(&uvcg_camera_grp
.group
,
2215 "camera", &uvcg_camera_grp_type
);
2216 configfs_add_default_group(&uvcg_default_camera
.group
,
2217 &uvcg_camera_grp
.group
);
2219 config_group_init_type_name(&uvcg_default_output
.group
,
2220 "default", &uvcg_default_output_type
);
2221 config_group_init_type_name(&uvcg_output_grp
.group
,
2222 "output", &uvcg_output_grp_type
);
2223 configfs_add_default_group(&uvcg_default_output
.group
,
2224 &uvcg_output_grp
.group
);
2226 config_group_init_type_name(&uvcg_terminal_grp
.group
,
2227 "terminal", &uvcg_terminal_grp_type
);
2228 configfs_add_default_group(&uvcg_camera_grp
.group
,
2229 &uvcg_terminal_grp
.group
);
2230 configfs_add_default_group(&uvcg_output_grp
.group
,
2231 &uvcg_terminal_grp
.group
);
2233 config_group_init_type_name(&uvcg_control_class_fs
.group
,
2234 "fs", &uvcg_control_class_type
);
2235 config_group_init_type_name(&uvcg_control_class_ss
.group
,
2236 "ss", &uvcg_control_class_type
);
2237 config_group_init_type_name(&uvcg_control_class_grp
.group
,
2239 &uvcg_control_class_grp_type
);
2240 configfs_add_default_group(&uvcg_control_class_fs
.group
,
2241 &uvcg_control_class_grp
.group
);
2242 configfs_add_default_group(&uvcg_control_class_ss
.group
,
2243 &uvcg_control_class_grp
.group
);
2245 config_group_init_type_name(&uvcg_control_grp
.group
,
2247 &uvcg_control_grp_type
);
2248 configfs_add_default_group(&uvcg_control_header_grp
.group
,
2249 &uvcg_control_grp
.group
);
2250 configfs_add_default_group(&uvcg_processing_grp
.group
,
2251 &uvcg_control_grp
.group
);
2252 configfs_add_default_group(&uvcg_terminal_grp
.group
,
2253 &uvcg_control_grp
.group
);
2254 configfs_add_default_group(&uvcg_control_class_grp
.group
,
2255 &uvcg_control_grp
.group
);
2257 config_group_init_type_name(&uvcg_streaming_header_grp
.group
,
2259 &uvcg_streaming_header_grp_type
);
2260 config_group_init_type_name(&uvcg_uncompressed_grp
.group
,
2262 &uvcg_uncompressed_grp_type
);
2263 config_group_init_type_name(&uvcg_mjpeg_grp
.group
,
2265 &uvcg_mjpeg_grp_type
);
2266 config_group_init_type_name(&uvcg_default_color_matching
.group
,
2268 &uvcg_default_color_matching_type
);
2269 config_group_init_type_name(&uvcg_color_matching_grp
.group
,
2271 &uvcg_color_matching_grp_type
);
2272 configfs_add_default_group(&uvcg_default_color_matching
.group
,
2273 &uvcg_color_matching_grp
.group
);
2275 config_group_init_type_name(&uvcg_streaming_class_fs
.group
,
2276 "fs", &uvcg_streaming_class_type
);
2277 config_group_init_type_name(&uvcg_streaming_class_hs
.group
,
2278 "hs", &uvcg_streaming_class_type
);
2279 config_group_init_type_name(&uvcg_streaming_class_ss
.group
,
2280 "ss", &uvcg_streaming_class_type
);
2281 config_group_init_type_name(&uvcg_streaming_class_grp
.group
,
2282 "class", &uvcg_streaming_class_grp_type
);
2283 configfs_add_default_group(&uvcg_streaming_class_fs
.group
,
2284 &uvcg_streaming_class_grp
.group
);
2285 configfs_add_default_group(&uvcg_streaming_class_hs
.group
,
2286 &uvcg_streaming_class_grp
.group
);
2287 configfs_add_default_group(&uvcg_streaming_class_ss
.group
,
2288 &uvcg_streaming_class_grp
.group
);
2290 config_group_init_type_name(&uvcg_streaming_grp
.group
,
2291 "streaming", &uvcg_streaming_grp_type
);
2292 configfs_add_default_group(&uvcg_streaming_header_grp
.group
,
2293 &uvcg_streaming_grp
.group
);
2294 configfs_add_default_group(&uvcg_uncompressed_grp
.group
,
2295 &uvcg_streaming_grp
.group
);
2296 configfs_add_default_group(&uvcg_mjpeg_grp
.group
,
2297 &uvcg_streaming_grp
.group
);
2298 configfs_add_default_group(&uvcg_color_matching_grp
.group
,
2299 &uvcg_streaming_grp
.group
);
2300 configfs_add_default_group(&uvcg_streaming_class_grp
.group
,
2301 &uvcg_streaming_grp
.group
);
2303 config_group_init_type_name(&opts
->func_inst
.group
,
2306 configfs_add_default_group(&uvcg_control_grp
.group
,
2307 &opts
->func_inst
.group
);
2308 configfs_add_default_group(&uvcg_streaming_grp
.group
,
2309 &opts
->func_inst
.group
);