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 CONFIGFS_ATTR_OPS_RO(_item) \
21 static ssize_t _item##_attr_show(struct config_item *item, \
22 struct configfs_attribute *attr, \
25 struct _item *_item = to_##_item(item); \
26 struct _item##_attribute *_item##_attr = \
27 container_of(attr, struct _item##_attribute, attr); \
30 if (_item##_attr->show) \
31 ret = _item##_attr->show(_item, page); \
35 static inline struct f_uvc_opts
*to_f_uvc_opts(struct config_item
*item
);
37 /* control/header/<NAME> */
38 DECLARE_UVC_HEADER_DESCRIPTOR(1);
40 struct uvcg_control_header
{
41 struct config_item item
;
42 struct UVC_HEADER_DESCRIPTOR(1) desc
;
46 static struct uvcg_control_header
*to_uvcg_control_header(struct config_item
*item
)
48 return container_of(item
, struct uvcg_control_header
, item
);
51 CONFIGFS_ATTR_STRUCT(uvcg_control_header
);
52 CONFIGFS_ATTR_OPS(uvcg_control_header
);
54 static struct configfs_item_operations uvcg_control_header_item_ops
= {
55 .show_attribute
= uvcg_control_header_attr_show
,
56 .store_attribute
= uvcg_control_header_attr_store
,
59 #define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
60 static ssize_t uvcg_control_header_##cname##_show( \
61 struct uvcg_control_header *ch, char *page) \
63 struct f_uvc_opts *opts; \
64 struct config_item *opts_item; \
65 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
68 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
70 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
71 opts = to_f_uvc_opts(opts_item); \
73 mutex_lock(&opts->lock); \
74 result = sprintf(page, "%d\n", conv(ch->desc.aname)); \
75 mutex_unlock(&opts->lock); \
77 mutex_unlock(su_mutex); \
82 uvcg_control_header_##cname##_store(struct uvcg_control_header *ch, \
83 const char *page, size_t len) \
85 struct f_uvc_opts *opts; \
86 struct config_item *opts_item; \
87 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
91 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
93 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
94 opts = to_f_uvc_opts(opts_item); \
96 mutex_lock(&opts->lock); \
97 if (ch->linked || opts->refcnt) { \
102 ret = str2u(page, 0, &num); \
110 ch->desc.aname = vnoc(num); \
113 mutex_unlock(&opts->lock); \
114 mutex_unlock(su_mutex); \
118 static struct uvcg_control_header_attribute \
119 uvcg_control_header_##cname = \
120 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
121 uvcg_control_header_##cname##_show, \
122 uvcg_control_header_##cname##_store)
124 UVCG_CTRL_HDR_ATTR(bcd_uvc
, bcdUVC
, le16_to_cpu
, kstrtou16
, u16
, cpu_to_le16
,
127 UVCG_CTRL_HDR_ATTR(dw_clock_frequency
, dwClockFrequency
, le32_to_cpu
, kstrtou32
,
128 u32
, cpu_to_le32
, 0x7fffffff);
130 #undef UVCG_CTRL_HDR_ATTR
132 static struct configfs_attribute
*uvcg_control_header_attrs
[] = {
133 &uvcg_control_header_bcd_uvc
.attr
,
134 &uvcg_control_header_dw_clock_frequency
.attr
,
138 static struct config_item_type uvcg_control_header_type
= {
139 .ct_item_ops
= &uvcg_control_header_item_ops
,
140 .ct_attrs
= uvcg_control_header_attrs
,
141 .ct_owner
= THIS_MODULE
,
144 static struct config_item
*uvcg_control_header_make(struct config_group
*group
,
147 struct uvcg_control_header
*h
;
149 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
151 return ERR_PTR(-ENOMEM
);
153 h
->desc
.bLength
= UVC_DT_HEADER_SIZE(1);
154 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
155 h
->desc
.bDescriptorSubType
= UVC_VC_HEADER
;
156 h
->desc
.bcdUVC
= cpu_to_le16(0x0100);
157 h
->desc
.dwClockFrequency
= cpu_to_le32(48000000);
159 config_item_init_type_name(&h
->item
, name
, &uvcg_control_header_type
);
164 static void uvcg_control_header_drop(struct config_group
*group
,
165 struct config_item
*item
)
167 struct uvcg_control_header
*h
= to_uvcg_control_header(item
);
173 static struct uvcg_control_header_grp
{
174 struct config_group group
;
175 } uvcg_control_header_grp
;
177 static struct configfs_group_operations uvcg_control_header_grp_ops
= {
178 .make_item
= uvcg_control_header_make
,
179 .drop_item
= uvcg_control_header_drop
,
182 static struct config_item_type uvcg_control_header_grp_type
= {
183 .ct_group_ops
= &uvcg_control_header_grp_ops
,
184 .ct_owner
= THIS_MODULE
,
187 /* control/processing/default */
188 static struct uvcg_default_processing
{
189 struct config_group group
;
190 } uvcg_default_processing
;
192 static inline struct uvcg_default_processing
193 *to_uvcg_default_processing(struct config_item
*item
)
195 return container_of(to_config_group(item
),
196 struct uvcg_default_processing
, group
);
199 CONFIGFS_ATTR_STRUCT(uvcg_default_processing
);
200 CONFIGFS_ATTR_OPS_RO(uvcg_default_processing
);
202 static struct configfs_item_operations uvcg_default_processing_item_ops
= {
203 .show_attribute
= uvcg_default_processing_attr_show
,
206 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
207 static ssize_t uvcg_default_processing_##cname##_show( \
208 struct uvcg_default_processing *dp, char *page) \
210 struct f_uvc_opts *opts; \
211 struct config_item *opts_item; \
212 struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
213 struct uvc_processing_unit_descriptor *pd; \
216 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
218 opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \
219 opts = to_f_uvc_opts(opts_item); \
220 pd = &opts->uvc_processing; \
222 mutex_lock(&opts->lock); \
223 result = sprintf(page, "%d\n", conv(pd->aname)); \
224 mutex_unlock(&opts->lock); \
226 mutex_unlock(su_mutex); \
230 static struct uvcg_default_processing_attribute \
231 uvcg_default_processing_##cname = \
232 __CONFIGFS_ATTR_RO(aname, uvcg_default_processing_##cname##_show)
234 #define identity_conv(x) (x)
236 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id
, bUnitID
, identity_conv
);
237 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id
, bSourceID
, identity_conv
);
238 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier
, wMaxMultiplier
, le16_to_cpu
);
239 UVCG_DEFAULT_PROCESSING_ATTR(i_processing
, iProcessing
, identity_conv
);
243 #undef UVCG_DEFAULT_PROCESSING_ATTR
245 static ssize_t
uvcg_default_processing_bm_controls_show(
246 struct uvcg_default_processing
*dp
, char *page
)
248 struct f_uvc_opts
*opts
;
249 struct config_item
*opts_item
;
250 struct mutex
*su_mutex
= &dp
->group
.cg_subsys
->su_mutex
;
251 struct uvc_processing_unit_descriptor
*pd
;
255 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
257 opts_item
= dp
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
258 opts
= to_f_uvc_opts(opts_item
);
259 pd
= &opts
->uvc_processing
;
261 mutex_lock(&opts
->lock
);
262 for (result
= 0, i
= 0; i
< pd
->bControlSize
; ++i
) {
263 result
+= sprintf(pg
, "%d\n", pd
->bmControls
[i
]);
266 mutex_unlock(&opts
->lock
);
268 mutex_unlock(su_mutex
);
273 static struct uvcg_default_processing_attribute
274 uvcg_default_processing_bm_controls
=
275 __CONFIGFS_ATTR_RO(bmControls
,
276 uvcg_default_processing_bm_controls_show
);
278 static struct configfs_attribute
*uvcg_default_processing_attrs
[] = {
279 &uvcg_default_processing_b_unit_id
.attr
,
280 &uvcg_default_processing_b_source_id
.attr
,
281 &uvcg_default_processing_w_max_multiplier
.attr
,
282 &uvcg_default_processing_bm_controls
.attr
,
283 &uvcg_default_processing_i_processing
.attr
,
287 static struct config_item_type uvcg_default_processing_type
= {
288 .ct_item_ops
= &uvcg_default_processing_item_ops
,
289 .ct_attrs
= uvcg_default_processing_attrs
,
290 .ct_owner
= THIS_MODULE
,
293 /* struct uvcg_processing {}; */
295 static struct config_group
*uvcg_processing_default_groups
[] = {
296 &uvcg_default_processing
.group
,
300 /* control/processing */
301 static struct uvcg_processing_grp
{
302 struct config_group group
;
303 } uvcg_processing_grp
;
305 static struct config_item_type uvcg_processing_grp_type
= {
306 .ct_owner
= THIS_MODULE
,
309 /* control/terminal/camera/default */
310 static struct uvcg_default_camera
{
311 struct config_group group
;
312 } uvcg_default_camera
;
314 static inline struct uvcg_default_camera
315 *to_uvcg_default_camera(struct config_item
*item
)
317 return container_of(to_config_group(item
),
318 struct uvcg_default_camera
, group
);
321 CONFIGFS_ATTR_STRUCT(uvcg_default_camera
);
322 CONFIGFS_ATTR_OPS_RO(uvcg_default_camera
);
324 static struct configfs_item_operations uvcg_default_camera_item_ops
= {
325 .show_attribute
= uvcg_default_camera_attr_show
,
328 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
329 static ssize_t uvcg_default_camera_##cname##_show( \
330 struct uvcg_default_camera *dc, char *page) \
332 struct f_uvc_opts *opts; \
333 struct config_item *opts_item; \
334 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
335 struct uvc_camera_terminal_descriptor *cd; \
338 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
340 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> \
342 opts = to_f_uvc_opts(opts_item); \
343 cd = &opts->uvc_camera_terminal; \
345 mutex_lock(&opts->lock); \
346 result = sprintf(page, "%d\n", conv(cd->aname)); \
347 mutex_unlock(&opts->lock); \
349 mutex_unlock(su_mutex); \
354 static struct uvcg_default_camera_attribute \
355 uvcg_default_camera_##cname = \
356 __CONFIGFS_ATTR_RO(aname, uvcg_default_camera_##cname##_show)
358 #define identity_conv(x) (x)
360 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id
, bTerminalID
, identity_conv
);
361 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type
, wTerminalType
, le16_to_cpu
);
362 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal
, bAssocTerminal
, identity_conv
);
363 UVCG_DEFAULT_CAMERA_ATTR(i_terminal
, iTerminal
, identity_conv
);
364 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min
, wObjectiveFocalLengthMin
,
366 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max
, wObjectiveFocalLengthMax
,
368 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length
, wOcularFocalLength
,
373 #undef UVCG_DEFAULT_CAMERA_ATTR
375 static ssize_t
uvcg_default_camera_bm_controls_show(
376 struct uvcg_default_camera
*dc
, char *page
)
378 struct f_uvc_opts
*opts
;
379 struct config_item
*opts_item
;
380 struct mutex
*su_mutex
= &dc
->group
.cg_subsys
->su_mutex
;
381 struct uvc_camera_terminal_descriptor
*cd
;
385 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
387 opts_item
= dc
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
->
389 opts
= to_f_uvc_opts(opts_item
);
390 cd
= &opts
->uvc_camera_terminal
;
392 mutex_lock(&opts
->lock
);
393 for (result
= 0, i
= 0; i
< cd
->bControlSize
; ++i
) {
394 result
+= sprintf(pg
, "%d\n", cd
->bmControls
[i
]);
397 mutex_unlock(&opts
->lock
);
399 mutex_unlock(su_mutex
);
403 static struct uvcg_default_camera_attribute
404 uvcg_default_camera_bm_controls
=
405 __CONFIGFS_ATTR_RO(bmControls
, uvcg_default_camera_bm_controls_show
);
407 static struct configfs_attribute
*uvcg_default_camera_attrs
[] = {
408 &uvcg_default_camera_b_terminal_id
.attr
,
409 &uvcg_default_camera_w_terminal_type
.attr
,
410 &uvcg_default_camera_b_assoc_terminal
.attr
,
411 &uvcg_default_camera_i_terminal
.attr
,
412 &uvcg_default_camera_w_objective_focal_length_min
.attr
,
413 &uvcg_default_camera_w_objective_focal_length_max
.attr
,
414 &uvcg_default_camera_w_ocular_focal_length
.attr
,
415 &uvcg_default_camera_bm_controls
.attr
,
419 static struct config_item_type uvcg_default_camera_type
= {
420 .ct_item_ops
= &uvcg_default_camera_item_ops
,
421 .ct_attrs
= uvcg_default_camera_attrs
,
422 .ct_owner
= THIS_MODULE
,
425 /* struct uvcg_camera {}; */
427 static struct config_group
*uvcg_camera_default_groups
[] = {
428 &uvcg_default_camera
.group
,
432 /* control/terminal/camera */
433 static struct uvcg_camera_grp
{
434 struct config_group group
;
437 static struct config_item_type uvcg_camera_grp_type
= {
438 .ct_owner
= THIS_MODULE
,
441 /* control/terminal/output/default */
442 static struct uvcg_default_output
{
443 struct config_group group
;
444 } uvcg_default_output
;
446 static inline struct uvcg_default_output
447 *to_uvcg_default_output(struct config_item
*item
)
449 return container_of(to_config_group(item
),
450 struct uvcg_default_output
, group
);
453 CONFIGFS_ATTR_STRUCT(uvcg_default_output
);
454 CONFIGFS_ATTR_OPS_RO(uvcg_default_output
);
456 static struct configfs_item_operations uvcg_default_output_item_ops
= {
457 .show_attribute
= uvcg_default_output_attr_show
,
460 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
461 static ssize_t uvcg_default_output_##cname##_show( \
462 struct uvcg_default_output *dout, char *page) \
464 struct f_uvc_opts *opts; \
465 struct config_item *opts_item; \
466 struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
467 struct uvc_output_terminal_descriptor *cd; \
470 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
472 opts_item = dout->group.cg_item.ci_parent->ci_parent-> \
473 ci_parent->ci_parent; \
474 opts = to_f_uvc_opts(opts_item); \
475 cd = &opts->uvc_output_terminal; \
477 mutex_lock(&opts->lock); \
478 result = sprintf(page, "%d\n", conv(cd->aname)); \
479 mutex_unlock(&opts->lock); \
481 mutex_unlock(su_mutex); \
486 static struct uvcg_default_output_attribute \
487 uvcg_default_output_##cname = \
488 __CONFIGFS_ATTR_RO(aname, uvcg_default_output_##cname##_show)
490 #define identity_conv(x) (x)
492 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id
, bTerminalID
, identity_conv
);
493 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type
, wTerminalType
, le16_to_cpu
);
494 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal
, bAssocTerminal
, identity_conv
);
495 UVCG_DEFAULT_OUTPUT_ATTR(b_source_id
, bSourceID
, identity_conv
);
496 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal
, iTerminal
, identity_conv
);
500 #undef UVCG_DEFAULT_OUTPUT_ATTR
502 static struct configfs_attribute
*uvcg_default_output_attrs
[] = {
503 &uvcg_default_output_b_terminal_id
.attr
,
504 &uvcg_default_output_w_terminal_type
.attr
,
505 &uvcg_default_output_b_assoc_terminal
.attr
,
506 &uvcg_default_output_b_source_id
.attr
,
507 &uvcg_default_output_i_terminal
.attr
,
511 static struct config_item_type uvcg_default_output_type
= {
512 .ct_item_ops
= &uvcg_default_output_item_ops
,
513 .ct_attrs
= uvcg_default_output_attrs
,
514 .ct_owner
= THIS_MODULE
,
517 /* struct uvcg_output {}; */
519 static struct config_group
*uvcg_output_default_groups
[] = {
520 &uvcg_default_output
.group
,
524 /* control/terminal/output */
525 static struct uvcg_output_grp
{
526 struct config_group group
;
529 static struct config_item_type uvcg_output_grp_type
= {
530 .ct_owner
= THIS_MODULE
,
533 static struct config_group
*uvcg_terminal_default_groups
[] = {
534 &uvcg_camera_grp
.group
,
535 &uvcg_output_grp
.group
,
539 /* control/terminal */
540 static struct uvcg_terminal_grp
{
541 struct config_group group
;
544 static struct config_item_type uvcg_terminal_grp_type
= {
545 .ct_owner
= THIS_MODULE
,
548 /* control/class/{fs} */
549 static struct uvcg_control_class
{
550 struct config_group group
;
551 } uvcg_control_class_fs
, uvcg_control_class_ss
;
554 static inline struct uvc_descriptor_header
555 **uvcg_get_ctl_class_arr(struct config_item
*i
, struct f_uvc_opts
*o
)
557 struct uvcg_control_class
*cl
= container_of(to_config_group(i
),
558 struct uvcg_control_class
, group
);
560 if (cl
== &uvcg_control_class_fs
)
561 return o
->uvc_fs_control_cls
;
563 if (cl
== &uvcg_control_class_ss
)
564 return o
->uvc_ss_control_cls
;
569 static int uvcg_control_class_allow_link(struct config_item
*src
,
570 struct config_item
*target
)
572 struct config_item
*control
, *header
;
573 struct f_uvc_opts
*opts
;
574 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
575 struct uvc_descriptor_header
**class_array
;
576 struct uvcg_control_header
*target_hdr
;
579 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
581 control
= src
->ci_parent
->ci_parent
;
582 header
= config_group_find_item(to_config_group(control
), "header");
583 if (!header
|| target
->ci_parent
!= header
)
586 opts
= to_f_uvc_opts(control
->ci_parent
);
588 mutex_lock(&opts
->lock
);
590 class_array
= uvcg_get_ctl_class_arr(src
, opts
);
593 if (opts
->refcnt
|| class_array
[0]) {
598 target_hdr
= to_uvcg_control_header(target
);
599 ++target_hdr
->linked
;
600 class_array
[0] = (struct uvc_descriptor_header
*)&target_hdr
->desc
;
604 mutex_unlock(&opts
->lock
);
606 mutex_unlock(su_mutex
);
610 static int uvcg_control_class_drop_link(struct config_item
*src
,
611 struct config_item
*target
)
613 struct config_item
*control
, *header
;
614 struct f_uvc_opts
*opts
;
615 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
616 struct uvc_descriptor_header
**class_array
;
617 struct uvcg_control_header
*target_hdr
;
620 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
622 control
= src
->ci_parent
->ci_parent
;
623 header
= config_group_find_item(to_config_group(control
), "header");
624 if (!header
|| target
->ci_parent
!= header
)
627 opts
= to_f_uvc_opts(control
->ci_parent
);
629 mutex_lock(&opts
->lock
);
631 class_array
= uvcg_get_ctl_class_arr(src
, opts
);
639 target_hdr
= to_uvcg_control_header(target
);
640 --target_hdr
->linked
;
641 class_array
[0] = NULL
;
645 mutex_unlock(&opts
->lock
);
647 mutex_unlock(su_mutex
);
651 static struct configfs_item_operations uvcg_control_class_item_ops
= {
652 .allow_link
= uvcg_control_class_allow_link
,
653 .drop_link
= uvcg_control_class_drop_link
,
656 static struct config_item_type uvcg_control_class_type
= {
657 .ct_item_ops
= &uvcg_control_class_item_ops
,
658 .ct_owner
= THIS_MODULE
,
661 static struct config_group
*uvcg_control_class_default_groups
[] = {
662 &uvcg_control_class_fs
.group
,
663 &uvcg_control_class_ss
.group
,
668 static struct uvcg_control_class_grp
{
669 struct config_group group
;
670 } uvcg_control_class_grp
;
672 static struct config_item_type uvcg_control_class_grp_type
= {
673 .ct_owner
= THIS_MODULE
,
676 static struct config_group
*uvcg_control_default_groups
[] = {
677 &uvcg_control_header_grp
.group
,
678 &uvcg_processing_grp
.group
,
679 &uvcg_terminal_grp
.group
,
680 &uvcg_control_class_grp
.group
,
685 static struct uvcg_control_grp
{
686 struct config_group group
;
689 static struct config_item_type uvcg_control_grp_type
= {
690 .ct_owner
= THIS_MODULE
,
693 /* streaming/uncompressed */
694 static struct uvcg_uncompressed_grp
{
695 struct config_group group
;
696 } uvcg_uncompressed_grp
;
698 /* streaming/mjpeg */
699 static struct uvcg_mjpeg_grp
{
700 struct config_group group
;
703 static struct config_item
*fmt_parent
[] = {
704 &uvcg_uncompressed_grp
.group
.cg_item
,
705 &uvcg_mjpeg_grp
.group
.cg_item
,
708 enum uvcg_format_type
{
709 UVCG_UNCOMPRESSED
= 0,
714 struct config_group group
;
715 enum uvcg_format_type type
;
718 __u8 bmaControls
[UVCG_STREAMING_CONTROL_SIZE
];
721 static struct uvcg_format
*to_uvcg_format(struct config_item
*item
)
723 return container_of(to_config_group(item
), struct uvcg_format
, group
);
726 static ssize_t
uvcg_format_bma_controls_show(struct uvcg_format
*f
, char *page
)
728 struct f_uvc_opts
*opts
;
729 struct config_item
*opts_item
;
730 struct mutex
*su_mutex
= &f
->group
.cg_subsys
->su_mutex
;
734 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
736 opts_item
= f
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
737 opts
= to_f_uvc_opts(opts_item
);
739 mutex_lock(&opts
->lock
);
740 result
= sprintf(pg
, "0x");
742 for (i
= 0; i
< UVCG_STREAMING_CONTROL_SIZE
; ++i
) {
743 result
+= sprintf(pg
, "%x\n", f
->bmaControls
[i
]);
746 mutex_unlock(&opts
->lock
);
748 mutex_unlock(su_mutex
);
752 static ssize_t
uvcg_format_bma_controls_store(struct uvcg_format
*ch
,
753 const char *page
, size_t len
)
755 struct f_uvc_opts
*opts
;
756 struct config_item
*opts_item
;
757 struct mutex
*su_mutex
= &ch
->group
.cg_subsys
->su_mutex
;
760 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
762 opts_item
= ch
->group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
763 opts
= to_f_uvc_opts(opts_item
);
765 mutex_lock(&opts
->lock
);
766 if (ch
->linked
|| opts
->refcnt
) {
771 if (len
< 4 || *page
!= '0' ||
772 (*(page
+ 1) != 'x' && *(page
+ 1) != 'X'))
774 ret
= hex2bin(ch
->bmaControls
, page
+ 2, 1);
779 mutex_unlock(&opts
->lock
);
780 mutex_unlock(su_mutex
);
784 struct uvcg_format_ptr
{
785 struct uvcg_format
*fmt
;
786 struct list_head entry
;
789 /* streaming/header/<NAME> */
790 struct uvcg_streaming_header
{
791 struct config_item item
;
792 struct uvc_input_header_descriptor desc
;
794 struct list_head formats
;
798 static struct uvcg_streaming_header
*to_uvcg_streaming_header(struct config_item
*item
)
800 return container_of(item
, struct uvcg_streaming_header
, item
);
803 CONFIGFS_ATTR_STRUCT(uvcg_streaming_header
);
804 CONFIGFS_ATTR_OPS(uvcg_streaming_header
);
806 static int uvcg_streaming_header_allow_link(struct config_item
*src
,
807 struct config_item
*target
)
809 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
810 struct config_item
*opts_item
;
811 struct f_uvc_opts
*opts
;
812 struct uvcg_streaming_header
*src_hdr
;
813 struct uvcg_format
*target_fmt
= NULL
;
814 struct uvcg_format_ptr
*format_ptr
;
815 int i
, ret
= -EINVAL
;
817 src_hdr
= to_uvcg_streaming_header(src
);
818 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
820 opts_item
= src
->ci_parent
->ci_parent
->ci_parent
;
821 opts
= to_f_uvc_opts(opts_item
);
823 mutex_lock(&opts
->lock
);
825 if (src_hdr
->linked
) {
830 for (i
= 0; i
< ARRAY_SIZE(fmt_parent
); ++i
)
831 if (target
->ci_parent
== fmt_parent
[i
])
833 if (i
== ARRAY_SIZE(fmt_parent
))
836 target_fmt
= container_of(to_config_group(target
), struct uvcg_format
,
841 format_ptr
= kzalloc(sizeof(*format_ptr
), GFP_KERNEL
);
847 format_ptr
->fmt
= target_fmt
;
848 list_add_tail(&format_ptr
->entry
, &src_hdr
->formats
);
852 mutex_unlock(&opts
->lock
);
853 mutex_unlock(su_mutex
);
857 static int uvcg_streaming_header_drop_link(struct config_item
*src
,
858 struct config_item
*target
)
860 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
861 struct config_item
*opts_item
;
862 struct f_uvc_opts
*opts
;
863 struct uvcg_streaming_header
*src_hdr
;
864 struct uvcg_format
*target_fmt
= NULL
;
865 struct uvcg_format_ptr
*format_ptr
, *tmp
;
868 src_hdr
= to_uvcg_streaming_header(src
);
869 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
871 opts_item
= src
->ci_parent
->ci_parent
->ci_parent
;
872 opts
= to_f_uvc_opts(opts_item
);
874 mutex_lock(&opts
->lock
);
875 target_fmt
= container_of(to_config_group(target
), struct uvcg_format
,
880 list_for_each_entry_safe(format_ptr
, tmp
, &src_hdr
->formats
, entry
)
881 if (format_ptr
->fmt
== target_fmt
) {
882 list_del(&format_ptr
->entry
);
889 mutex_unlock(&opts
->lock
);
890 mutex_unlock(su_mutex
);
895 static struct configfs_item_operations uvcg_streaming_header_item_ops
= {
896 .show_attribute
= uvcg_streaming_header_attr_show
,
897 .store_attribute
= uvcg_streaming_header_attr_store
,
898 .allow_link
= uvcg_streaming_header_allow_link
,
899 .drop_link
= uvcg_streaming_header_drop_link
,
902 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
903 static ssize_t uvcg_streaming_header_##cname##_show( \
904 struct uvcg_streaming_header *sh, char *page) \
906 struct f_uvc_opts *opts; \
907 struct config_item *opts_item; \
908 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
911 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
913 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
914 opts = to_f_uvc_opts(opts_item); \
916 mutex_lock(&opts->lock); \
917 result = sprintf(page, "%d\n", conv(sh->desc.aname)); \
918 mutex_unlock(&opts->lock); \
920 mutex_unlock(su_mutex); \
924 static struct uvcg_streaming_header_attribute \
925 uvcg_streaming_header_##cname = \
926 __CONFIGFS_ATTR_RO(aname, uvcg_streaming_header_##cname##_show)
928 #define identity_conv(x) (x)
930 UVCG_STREAMING_HEADER_ATTR(bm_info
, bmInfo
, identity_conv
);
931 UVCG_STREAMING_HEADER_ATTR(b_terminal_link
, bTerminalLink
, identity_conv
);
932 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method
, bStillCaptureMethod
,
934 UVCG_STREAMING_HEADER_ATTR(b_trigger_support
, bTriggerSupport
, identity_conv
);
935 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage
, bTriggerUsage
, identity_conv
);
939 #undef UVCG_STREAMING_HEADER_ATTR
941 static struct configfs_attribute
*uvcg_streaming_header_attrs
[] = {
942 &uvcg_streaming_header_bm_info
.attr
,
943 &uvcg_streaming_header_b_terminal_link
.attr
,
944 &uvcg_streaming_header_b_still_capture_method
.attr
,
945 &uvcg_streaming_header_b_trigger_support
.attr
,
946 &uvcg_streaming_header_b_trigger_usage
.attr
,
950 static struct config_item_type uvcg_streaming_header_type
= {
951 .ct_item_ops
= &uvcg_streaming_header_item_ops
,
952 .ct_attrs
= uvcg_streaming_header_attrs
,
953 .ct_owner
= THIS_MODULE
,
956 static struct config_item
957 *uvcg_streaming_header_make(struct config_group
*group
, const char *name
)
959 struct uvcg_streaming_header
*h
;
961 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
963 return ERR_PTR(-ENOMEM
);
965 INIT_LIST_HEAD(&h
->formats
);
966 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
967 h
->desc
.bDescriptorSubType
= UVC_VS_INPUT_HEADER
;
968 h
->desc
.bTerminalLink
= 3;
969 h
->desc
.bControlSize
= UVCG_STREAMING_CONTROL_SIZE
;
971 config_item_init_type_name(&h
->item
, name
, &uvcg_streaming_header_type
);
976 static void uvcg_streaming_header_drop(struct config_group
*group
,
977 struct config_item
*item
)
979 struct uvcg_streaming_header
*h
= to_uvcg_streaming_header(item
);
984 /* streaming/header */
985 static struct uvcg_streaming_header_grp
{
986 struct config_group group
;
987 } uvcg_streaming_header_grp
;
989 static struct configfs_group_operations uvcg_streaming_header_grp_ops
= {
990 .make_item
= uvcg_streaming_header_make
,
991 .drop_item
= uvcg_streaming_header_drop
,
994 static struct config_item_type uvcg_streaming_header_grp_type
= {
995 .ct_group_ops
= &uvcg_streaming_header_grp_ops
,
996 .ct_owner
= THIS_MODULE
,
999 /* streaming/<mode>/<format>/<NAME> */
1003 u8 b_descriptor_type
;
1004 u8 b_descriptor_subtype
;
1009 u32 dw_min_bit_rate
;
1010 u32 dw_max_bit_rate
;
1011 u32 dw_max_video_frame_buffer_size
;
1012 u32 dw_default_frame_interval
;
1013 u8 b_frame_interval_type
;
1014 } __attribute__((packed
)) frame
;
1015 u32
*dw_frame_interval
;
1016 enum uvcg_format_type fmt_type
;
1017 struct config_item item
;
1020 static struct uvcg_frame
*to_uvcg_frame(struct config_item
*item
)
1022 return container_of(item
, struct uvcg_frame
, item
);
1025 CONFIGFS_ATTR_STRUCT(uvcg_frame
);
1026 CONFIGFS_ATTR_OPS(uvcg_frame
);
1028 static struct configfs_item_operations uvcg_frame_item_ops
= {
1029 .show_attribute
= uvcg_frame_attr_show
,
1030 .store_attribute
= uvcg_frame_attr_store
,
1033 #define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
1034 static ssize_t uvcg_frame_##cname##_show(struct uvcg_frame *f, char *page)\
1036 struct f_uvc_opts *opts; \
1037 struct config_item *opts_item; \
1038 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1041 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1043 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1044 opts = to_f_uvc_opts(opts_item); \
1046 mutex_lock(&opts->lock); \
1047 result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \
1048 mutex_unlock(&opts->lock); \
1050 mutex_unlock(su_mutex); \
1054 static ssize_t uvcg_frame_##cname##_store(struct uvcg_frame *f, \
1055 const char *page, size_t len)\
1057 struct f_uvc_opts *opts; \
1058 struct config_item *opts_item; \
1059 struct uvcg_format *fmt; \
1060 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1064 ret = kstrtou##bits(page, 0, &num); \
1068 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1070 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1071 opts = to_f_uvc_opts(opts_item); \
1072 fmt = to_uvcg_format(f->item.ci_parent); \
1074 mutex_lock(&opts->lock); \
1075 if (fmt->linked || opts->refcnt) { \
1080 f->frame.cname = to_little_endian(num); \
1083 mutex_unlock(&opts->lock); \
1084 mutex_unlock(su_mutex); \
1088 static struct uvcg_frame_attribute \
1089 uvcg_frame_##cname = \
1090 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
1091 uvcg_frame_##cname##_show, \
1092 uvcg_frame_##cname##_store)
1094 #define noop_conversion(x) (x)
1096 UVCG_FRAME_ATTR(bm_capabilities
, bmCapabilities
, noop_conversion
,
1097 noop_conversion
, 8);
1098 UVCG_FRAME_ATTR(w_width
, wWidth
, le16_to_cpu
, cpu_to_le16
, 16);
1099 UVCG_FRAME_ATTR(w_height
, wHeight
, le16_to_cpu
, cpu_to_le16
, 16);
1100 UVCG_FRAME_ATTR(dw_min_bit_rate
, dwMinBitRate
, le32_to_cpu
, cpu_to_le32
, 32);
1101 UVCG_FRAME_ATTR(dw_max_bit_rate
, dwMaxBitRate
, le32_to_cpu
, cpu_to_le32
, 32);
1102 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size
, dwMaxVideoFrameBufferSize
,
1103 le32_to_cpu
, cpu_to_le32
, 32);
1104 UVCG_FRAME_ATTR(dw_default_frame_interval
, dwDefaultFrameInterval
,
1105 le32_to_cpu
, cpu_to_le32
, 32);
1107 #undef noop_conversion
1109 #undef UVCG_FRAME_ATTR
1111 static ssize_t
uvcg_frame_dw_frame_interval_show(struct uvcg_frame
*frm
,
1114 struct f_uvc_opts
*opts
;
1115 struct config_item
*opts_item
;
1116 struct mutex
*su_mutex
= &frm
->item
.ci_group
->cg_subsys
->su_mutex
;
1120 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1122 opts_item
= frm
->item
.ci_parent
->ci_parent
->ci_parent
->ci_parent
;
1123 opts
= to_f_uvc_opts(opts_item
);
1125 mutex_lock(&opts
->lock
);
1126 for (result
= 0, i
= 0; i
< frm
->frame
.b_frame_interval_type
; ++i
) {
1127 result
+= sprintf(pg
, "%d\n",
1128 le32_to_cpu(frm
->dw_frame_interval
[i
]));
1131 mutex_unlock(&opts
->lock
);
1133 mutex_unlock(su_mutex
);
1137 static inline int __uvcg_count_frm_intrv(char *buf
, void *priv
)
1143 static inline int __uvcg_fill_frm_intrv(char *buf
, void *priv
)
1148 ret
= kstrtou32(buf
, 0, &num
);
1153 **interv
= cpu_to_le32(num
);
1159 static int __uvcg_iter_frm_intrv(const char *page
, size_t len
,
1160 int (*fun
)(char *, void *), void *priv
)
1162 /* sign, base 2 representation, newline, terminator */
1163 char buf
[1 + sizeof(u32
) * 8 + 1 + 1];
1164 const char *pg
= page
;
1170 while (pg
- page
< len
) {
1172 while (i
< sizeof(buf
) && (pg
- page
< len
) &&
1173 *pg
!= '\0' && *pg
!= '\n')
1175 if (i
== sizeof(buf
))
1177 while ((pg
- page
< len
) && (*pg
== '\0' || *pg
== '\n'))
1180 ret
= fun(buf
, priv
);
1188 static ssize_t
uvcg_frame_dw_frame_interval_store(struct uvcg_frame
*ch
,
1189 const char *page
, size_t len
)
1191 struct f_uvc_opts
*opts
;
1192 struct config_item
*opts_item
;
1193 struct uvcg_format
*fmt
;
1194 struct mutex
*su_mutex
= &ch
->item
.ci_group
->cg_subsys
->su_mutex
;
1196 u32
*frm_intrv
, *tmp
;
1198 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1200 opts_item
= ch
->item
.ci_parent
->ci_parent
->ci_parent
->ci_parent
;
1201 opts
= to_f_uvc_opts(opts_item
);
1202 fmt
= to_uvcg_format(ch
->item
.ci_parent
);
1204 mutex_lock(&opts
->lock
);
1205 if (fmt
->linked
|| opts
->refcnt
) {
1210 ret
= __uvcg_iter_frm_intrv(page
, len
, __uvcg_count_frm_intrv
, &n
);
1214 tmp
= frm_intrv
= kcalloc(n
, sizeof(u32
), GFP_KERNEL
);
1220 ret
= __uvcg_iter_frm_intrv(page
, len
, __uvcg_fill_frm_intrv
, &tmp
);
1226 kfree(ch
->dw_frame_interval
);
1227 ch
->dw_frame_interval
= frm_intrv
;
1228 ch
->frame
.b_frame_interval_type
= n
;
1232 mutex_unlock(&opts
->lock
);
1233 mutex_unlock(su_mutex
);
1237 static struct uvcg_frame_attribute
1238 uvcg_frame_dw_frame_interval
=
1239 __CONFIGFS_ATTR(dwFrameInterval
, S_IRUGO
| S_IWUSR
,
1240 uvcg_frame_dw_frame_interval_show
,
1241 uvcg_frame_dw_frame_interval_store
);
1243 static struct configfs_attribute
*uvcg_frame_attrs
[] = {
1244 &uvcg_frame_bm_capabilities
.attr
,
1245 &uvcg_frame_w_width
.attr
,
1246 &uvcg_frame_w_height
.attr
,
1247 &uvcg_frame_dw_min_bit_rate
.attr
,
1248 &uvcg_frame_dw_max_bit_rate
.attr
,
1249 &uvcg_frame_dw_max_video_frame_buffer_size
.attr
,
1250 &uvcg_frame_dw_default_frame_interval
.attr
,
1251 &uvcg_frame_dw_frame_interval
.attr
,
1255 static struct config_item_type uvcg_frame_type
= {
1256 .ct_item_ops
= &uvcg_frame_item_ops
,
1257 .ct_attrs
= uvcg_frame_attrs
,
1258 .ct_owner
= THIS_MODULE
,
1261 static struct config_item
*uvcg_frame_make(struct config_group
*group
,
1264 struct uvcg_frame
*h
;
1265 struct uvcg_format
*fmt
;
1266 struct f_uvc_opts
*opts
;
1267 struct config_item
*opts_item
;
1269 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1271 return ERR_PTR(-ENOMEM
);
1273 h
->frame
.b_descriptor_type
= USB_DT_CS_INTERFACE
;
1274 h
->frame
.b_frame_index
= 1;
1275 h
->frame
.w_width
= cpu_to_le16(640);
1276 h
->frame
.w_height
= cpu_to_le16(360);
1277 h
->frame
.dw_min_bit_rate
= cpu_to_le32(18432000);
1278 h
->frame
.dw_max_bit_rate
= cpu_to_le32(55296000);
1279 h
->frame
.dw_max_video_frame_buffer_size
= cpu_to_le32(460800);
1280 h
->frame
.dw_default_frame_interval
= cpu_to_le32(666666);
1282 opts_item
= group
->cg_item
.ci_parent
->ci_parent
->ci_parent
;
1283 opts
= to_f_uvc_opts(opts_item
);
1285 mutex_lock(&opts
->lock
);
1286 fmt
= to_uvcg_format(&group
->cg_item
);
1287 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
1288 h
->frame
.b_descriptor_subtype
= UVC_VS_FRAME_UNCOMPRESSED
;
1289 h
->fmt_type
= UVCG_UNCOMPRESSED
;
1290 } else if (fmt
->type
== UVCG_MJPEG
) {
1291 h
->frame
.b_descriptor_subtype
= UVC_VS_FRAME_MJPEG
;
1292 h
->fmt_type
= UVCG_MJPEG
;
1294 mutex_unlock(&opts
->lock
);
1296 return ERR_PTR(-EINVAL
);
1299 mutex_unlock(&opts
->lock
);
1301 config_item_init_type_name(&h
->item
, name
, &uvcg_frame_type
);
1306 static void uvcg_frame_drop(struct config_group
*group
, struct config_item
*item
)
1308 struct uvcg_frame
*h
= to_uvcg_frame(item
);
1309 struct uvcg_format
*fmt
;
1310 struct f_uvc_opts
*opts
;
1311 struct config_item
*opts_item
;
1313 opts_item
= group
->cg_item
.ci_parent
->ci_parent
->ci_parent
;
1314 opts
= to_f_uvc_opts(opts_item
);
1316 mutex_lock(&opts
->lock
);
1317 fmt
= to_uvcg_format(&group
->cg_item
);
1320 mutex_unlock(&opts
->lock
);
1323 /* streaming/uncompressed/<NAME> */
1324 struct uvcg_uncompressed
{
1325 struct uvcg_format fmt
;
1326 struct uvc_format_uncompressed desc
;
1329 static struct uvcg_uncompressed
*to_uvcg_uncompressed(struct config_item
*item
)
1331 return container_of(
1332 container_of(to_config_group(item
), struct uvcg_format
, group
),
1333 struct uvcg_uncompressed
, fmt
);
1336 CONFIGFS_ATTR_STRUCT(uvcg_uncompressed
);
1337 CONFIGFS_ATTR_OPS(uvcg_uncompressed
);
1339 static struct configfs_item_operations uvcg_uncompressed_item_ops
= {
1340 .show_attribute
= uvcg_uncompressed_attr_show
,
1341 .store_attribute
= uvcg_uncompressed_attr_store
,
1344 static struct configfs_group_operations uvcg_uncompressed_group_ops
= {
1345 .make_item
= uvcg_frame_make
,
1346 .drop_item
= uvcg_frame_drop
,
1349 static ssize_t
uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed
*ch
,
1352 struct f_uvc_opts
*opts
;
1353 struct config_item
*opts_item
;
1354 struct mutex
*su_mutex
= &ch
->fmt
.group
.cg_subsys
->su_mutex
;
1356 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1358 opts_item
= ch
->fmt
.group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
1359 opts
= to_f_uvc_opts(opts_item
);
1361 mutex_lock(&opts
->lock
);
1362 memcpy(page
, ch
->desc
.guidFormat
, sizeof(ch
->desc
.guidFormat
));
1363 mutex_unlock(&opts
->lock
);
1365 mutex_unlock(su_mutex
);
1367 return sizeof(ch
->desc
.guidFormat
);
1370 static ssize_t
uvcg_uncompressed_guid_format_store(struct uvcg_uncompressed
*ch
,
1371 const char *page
, size_t len
)
1373 struct f_uvc_opts
*opts
;
1374 struct config_item
*opts_item
;
1375 struct mutex
*su_mutex
= &ch
->fmt
.group
.cg_subsys
->su_mutex
;
1378 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
1380 opts_item
= ch
->fmt
.group
.cg_item
.ci_parent
->ci_parent
->ci_parent
;
1381 opts
= to_f_uvc_opts(opts_item
);
1383 mutex_lock(&opts
->lock
);
1384 if (ch
->fmt
.linked
|| opts
->refcnt
) {
1389 memcpy(ch
->desc
.guidFormat
, page
,
1390 min(sizeof(ch
->desc
.guidFormat
), len
));
1391 ret
= sizeof(ch
->desc
.guidFormat
);
1394 mutex_unlock(&opts
->lock
);
1395 mutex_unlock(su_mutex
);
1399 static struct uvcg_uncompressed_attribute uvcg_uncompressed_guid_format
=
1400 __CONFIGFS_ATTR(guidFormat
, S_IRUGO
| S_IWUSR
,
1401 uvcg_uncompressed_guid_format_show
,
1402 uvcg_uncompressed_guid_format_store
);
1405 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
1406 static ssize_t uvcg_uncompressed_##cname##_show( \
1407 struct uvcg_uncompressed *u, char *page) \
1409 struct f_uvc_opts *opts; \
1410 struct config_item *opts_item; \
1411 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1414 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1416 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1417 opts = to_f_uvc_opts(opts_item); \
1419 mutex_lock(&opts->lock); \
1420 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1421 mutex_unlock(&opts->lock); \
1423 mutex_unlock(su_mutex); \
1427 static struct uvcg_uncompressed_attribute \
1428 uvcg_uncompressed_##cname = \
1429 __CONFIGFS_ATTR_RO(aname, uvcg_uncompressed_##cname##_show)
1431 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
1432 static ssize_t uvcg_uncompressed_##cname##_show( \
1433 struct uvcg_uncompressed *u, char *page) \
1435 struct f_uvc_opts *opts; \
1436 struct config_item *opts_item; \
1437 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1440 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1442 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1443 opts = to_f_uvc_opts(opts_item); \
1445 mutex_lock(&opts->lock); \
1446 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1447 mutex_unlock(&opts->lock); \
1449 mutex_unlock(su_mutex); \
1454 uvcg_uncompressed_##cname##_store(struct uvcg_uncompressed *u, \
1455 const char *page, size_t len) \
1457 struct f_uvc_opts *opts; \
1458 struct config_item *opts_item; \
1459 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1463 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1465 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1466 opts = to_f_uvc_opts(opts_item); \
1468 mutex_lock(&opts->lock); \
1469 if (u->fmt.linked || opts->refcnt) { \
1474 ret = kstrtou8(page, 0, &num); \
1482 u->desc.aname = num; \
1485 mutex_unlock(&opts->lock); \
1486 mutex_unlock(su_mutex); \
1490 static struct uvcg_uncompressed_attribute \
1491 uvcg_uncompressed_##cname = \
1492 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
1493 uvcg_uncompressed_##cname##_show, \
1494 uvcg_uncompressed_##cname##_store)
1496 #define identity_conv(x) (x)
1498 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel
, bBitsPerPixel
, identity_conv
);
1499 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index
, bDefaultFrameIndex
,
1501 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x
, bAspectRatioX
, identity_conv
);
1502 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y
, bAspectRatioY
, identity_conv
);
1503 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags
, bmInterfaceFlags
, identity_conv
);
1505 #undef identity_conv
1507 #undef UVCG_UNCOMPRESSED_ATTR
1508 #undef UVCG_UNCOMPRESSED_ATTR_RO
1510 static inline ssize_t
1511 uvcg_uncompressed_bma_controls_show(struct uvcg_uncompressed
*unc
, char *page
)
1513 return uvcg_format_bma_controls_show(&unc
->fmt
, page
);
1516 static inline ssize_t
1517 uvcg_uncompressed_bma_controls_store(struct uvcg_uncompressed
*ch
,
1518 const char *page
, size_t len
)
1520 return uvcg_format_bma_controls_store(&ch
->fmt
, page
, len
);
1523 static struct uvcg_uncompressed_attribute uvcg_uncompressed_bma_controls
=
1524 __CONFIGFS_ATTR(bmaControls
, S_IRUGO
| S_IWUSR
,
1525 uvcg_uncompressed_bma_controls_show
,
1526 uvcg_uncompressed_bma_controls_store
);
1528 static struct configfs_attribute
*uvcg_uncompressed_attrs
[] = {
1529 &uvcg_uncompressed_guid_format
.attr
,
1530 &uvcg_uncompressed_b_bits_per_pixel
.attr
,
1531 &uvcg_uncompressed_b_default_frame_index
.attr
,
1532 &uvcg_uncompressed_b_aspect_ratio_x
.attr
,
1533 &uvcg_uncompressed_b_aspect_ratio_y
.attr
,
1534 &uvcg_uncompressed_bm_interface_flags
.attr
,
1535 &uvcg_uncompressed_bma_controls
.attr
,
1539 static struct config_item_type uvcg_uncompressed_type
= {
1540 .ct_item_ops
= &uvcg_uncompressed_item_ops
,
1541 .ct_group_ops
= &uvcg_uncompressed_group_ops
,
1542 .ct_attrs
= uvcg_uncompressed_attrs
,
1543 .ct_owner
= THIS_MODULE
,
1546 static struct config_group
*uvcg_uncompressed_make(struct config_group
*group
,
1549 static char guid
[] = {
1550 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
1551 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1553 struct uvcg_uncompressed
*h
;
1555 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1557 return ERR_PTR(-ENOMEM
);
1559 h
->desc
.bLength
= UVC_DT_FORMAT_UNCOMPRESSED_SIZE
;
1560 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
1561 h
->desc
.bDescriptorSubType
= UVC_VS_FORMAT_UNCOMPRESSED
;
1562 memcpy(h
->desc
.guidFormat
, guid
, sizeof(guid
));
1563 h
->desc
.bBitsPerPixel
= 16;
1564 h
->desc
.bDefaultFrameIndex
= 1;
1565 h
->desc
.bAspectRatioX
= 0;
1566 h
->desc
.bAspectRatioY
= 0;
1567 h
->desc
.bmInterfaceFlags
= 0;
1568 h
->desc
.bCopyProtect
= 0;
1570 h
->fmt
.type
= UVCG_UNCOMPRESSED
;
1571 config_group_init_type_name(&h
->fmt
.group
, name
,
1572 &uvcg_uncompressed_type
);
1574 return &h
->fmt
.group
;
1577 static void uvcg_uncompressed_drop(struct config_group
*group
,
1578 struct config_item
*item
)
1580 struct uvcg_uncompressed
*h
= to_uvcg_uncompressed(item
);
1585 static struct configfs_group_operations uvcg_uncompressed_grp_ops
= {
1586 .make_group
= uvcg_uncompressed_make
,
1587 .drop_item
= uvcg_uncompressed_drop
,
1590 static struct config_item_type uvcg_uncompressed_grp_type
= {
1591 .ct_group_ops
= &uvcg_uncompressed_grp_ops
,
1592 .ct_owner
= THIS_MODULE
,
1595 /* streaming/mjpeg/<NAME> */
1597 struct uvcg_format fmt
;
1598 struct uvc_format_mjpeg desc
;
1601 static struct uvcg_mjpeg
*to_uvcg_mjpeg(struct config_item
*item
)
1603 return container_of(
1604 container_of(to_config_group(item
), struct uvcg_format
, group
),
1605 struct uvcg_mjpeg
, fmt
);
1608 CONFIGFS_ATTR_STRUCT(uvcg_mjpeg
);
1609 CONFIGFS_ATTR_OPS(uvcg_mjpeg
);
1611 static struct configfs_item_operations uvcg_mjpeg_item_ops
= {
1612 .show_attribute
= uvcg_mjpeg_attr_show
,
1613 .store_attribute
= uvcg_mjpeg_attr_store
,
1616 static struct configfs_group_operations uvcg_mjpeg_group_ops
= {
1617 .make_item
= uvcg_frame_make
,
1618 .drop_item
= uvcg_frame_drop
,
1621 #define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
1622 static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
1624 struct f_uvc_opts *opts; \
1625 struct config_item *opts_item; \
1626 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1629 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1631 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1632 opts = to_f_uvc_opts(opts_item); \
1634 mutex_lock(&opts->lock); \
1635 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1636 mutex_unlock(&opts->lock); \
1638 mutex_unlock(su_mutex); \
1642 static struct uvcg_mjpeg_attribute \
1643 uvcg_mjpeg_##cname = \
1644 __CONFIGFS_ATTR_RO(aname, uvcg_mjpeg_##cname##_show)
1646 #define UVCG_MJPEG_ATTR(cname, aname, conv) \
1647 static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\
1649 struct f_uvc_opts *opts; \
1650 struct config_item *opts_item; \
1651 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1654 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1656 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1657 opts = to_f_uvc_opts(opts_item); \
1659 mutex_lock(&opts->lock); \
1660 result = sprintf(page, "%d\n", conv(u->desc.aname)); \
1661 mutex_unlock(&opts->lock); \
1663 mutex_unlock(su_mutex); \
1668 uvcg_mjpeg_##cname##_store(struct uvcg_mjpeg *u, \
1669 const char *page, size_t len) \
1671 struct f_uvc_opts *opts; \
1672 struct config_item *opts_item; \
1673 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1677 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1679 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1680 opts = to_f_uvc_opts(opts_item); \
1682 mutex_lock(&opts->lock); \
1683 if (u->fmt.linked || opts->refcnt) { \
1688 ret = kstrtou8(page, 0, &num); \
1696 u->desc.aname = num; \
1699 mutex_unlock(&opts->lock); \
1700 mutex_unlock(su_mutex); \
1704 static struct uvcg_mjpeg_attribute \
1705 uvcg_mjpeg_##cname = \
1706 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \
1707 uvcg_mjpeg_##cname##_show, \
1708 uvcg_mjpeg_##cname##_store)
1710 #define identity_conv(x) (x)
1712 UVCG_MJPEG_ATTR(b_default_frame_index
, bDefaultFrameIndex
,
1714 UVCG_MJPEG_ATTR_RO(bm_flags
, bmFlags
, identity_conv
);
1715 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x
, bAspectRatioX
, identity_conv
);
1716 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y
, bAspectRatioY
, identity_conv
);
1717 UVCG_MJPEG_ATTR_RO(bm_interface_flags
, bmInterfaceFlags
, identity_conv
);
1719 #undef identity_conv
1721 #undef UVCG_MJPEG_ATTR
1722 #undef UVCG_MJPEG_ATTR_RO
1724 static inline ssize_t
1725 uvcg_mjpeg_bma_controls_show(struct uvcg_mjpeg
*unc
, char *page
)
1727 return uvcg_format_bma_controls_show(&unc
->fmt
, page
);
1730 static inline ssize_t
1731 uvcg_mjpeg_bma_controls_store(struct uvcg_mjpeg
*ch
,
1732 const char *page
, size_t len
)
1734 return uvcg_format_bma_controls_store(&ch
->fmt
, page
, len
);
1737 static struct uvcg_mjpeg_attribute uvcg_mjpeg_bma_controls
=
1738 __CONFIGFS_ATTR(bmaControls
, S_IRUGO
| S_IWUSR
,
1739 uvcg_mjpeg_bma_controls_show
,
1740 uvcg_mjpeg_bma_controls_store
);
1742 static struct configfs_attribute
*uvcg_mjpeg_attrs
[] = {
1743 &uvcg_mjpeg_b_default_frame_index
.attr
,
1744 &uvcg_mjpeg_bm_flags
.attr
,
1745 &uvcg_mjpeg_b_aspect_ratio_x
.attr
,
1746 &uvcg_mjpeg_b_aspect_ratio_y
.attr
,
1747 &uvcg_mjpeg_bm_interface_flags
.attr
,
1748 &uvcg_mjpeg_bma_controls
.attr
,
1752 static struct config_item_type uvcg_mjpeg_type
= {
1753 .ct_item_ops
= &uvcg_mjpeg_item_ops
,
1754 .ct_group_ops
= &uvcg_mjpeg_group_ops
,
1755 .ct_attrs
= uvcg_mjpeg_attrs
,
1756 .ct_owner
= THIS_MODULE
,
1759 static struct config_group
*uvcg_mjpeg_make(struct config_group
*group
,
1762 struct uvcg_mjpeg
*h
;
1764 h
= kzalloc(sizeof(*h
), GFP_KERNEL
);
1766 return ERR_PTR(-ENOMEM
);
1768 h
->desc
.bLength
= UVC_DT_FORMAT_MJPEG_SIZE
;
1769 h
->desc
.bDescriptorType
= USB_DT_CS_INTERFACE
;
1770 h
->desc
.bDescriptorSubType
= UVC_VS_FORMAT_MJPEG
;
1771 h
->desc
.bDefaultFrameIndex
= 1;
1772 h
->desc
.bAspectRatioX
= 0;
1773 h
->desc
.bAspectRatioY
= 0;
1774 h
->desc
.bmInterfaceFlags
= 0;
1775 h
->desc
.bCopyProtect
= 0;
1777 h
->fmt
.type
= UVCG_MJPEG
;
1778 config_group_init_type_name(&h
->fmt
.group
, name
,
1781 return &h
->fmt
.group
;
1784 static void uvcg_mjpeg_drop(struct config_group
*group
,
1785 struct config_item
*item
)
1787 struct uvcg_mjpeg
*h
= to_uvcg_mjpeg(item
);
1792 static struct configfs_group_operations uvcg_mjpeg_grp_ops
= {
1793 .make_group
= uvcg_mjpeg_make
,
1794 .drop_item
= uvcg_mjpeg_drop
,
1797 static struct config_item_type uvcg_mjpeg_grp_type
= {
1798 .ct_group_ops
= &uvcg_mjpeg_grp_ops
,
1799 .ct_owner
= THIS_MODULE
,
1802 /* streaming/color_matching/default */
1803 static struct uvcg_default_color_matching
{
1804 struct config_group group
;
1805 } uvcg_default_color_matching
;
1807 static inline struct uvcg_default_color_matching
1808 *to_uvcg_default_color_matching(struct config_item
*item
)
1810 return container_of(to_config_group(item
),
1811 struct uvcg_default_color_matching
, group
);
1814 CONFIGFS_ATTR_STRUCT(uvcg_default_color_matching
);
1815 CONFIGFS_ATTR_OPS_RO(uvcg_default_color_matching
);
1817 static struct configfs_item_operations uvcg_default_color_matching_item_ops
= {
1818 .show_attribute
= uvcg_default_color_matching_attr_show
,
1821 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
1822 static ssize_t uvcg_default_color_matching_##cname##_show( \
1823 struct uvcg_default_color_matching *dc, char *page) \
1825 struct f_uvc_opts *opts; \
1826 struct config_item *opts_item; \
1827 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
1828 struct uvc_color_matching_descriptor *cd; \
1831 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1833 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \
1834 opts = to_f_uvc_opts(opts_item); \
1835 cd = &opts->uvc_color_matching; \
1837 mutex_lock(&opts->lock); \
1838 result = sprintf(page, "%d\n", conv(cd->aname)); \
1839 mutex_unlock(&opts->lock); \
1841 mutex_unlock(su_mutex); \
1845 static struct uvcg_default_color_matching_attribute \
1846 uvcg_default_color_matching_##cname = \
1847 __CONFIGFS_ATTR_RO(aname, uvcg_default_color_matching_##cname##_show)
1849 #define identity_conv(x) (x)
1851 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries
, bColorPrimaries
,
1853 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics
,
1854 bTransferCharacteristics
, identity_conv
);
1855 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients
, bMatrixCoefficients
,
1858 #undef identity_conv
1860 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1862 static struct configfs_attribute
*uvcg_default_color_matching_attrs
[] = {
1863 &uvcg_default_color_matching_b_color_primaries
.attr
,
1864 &uvcg_default_color_matching_b_transfer_characteristics
.attr
,
1865 &uvcg_default_color_matching_b_matrix_coefficients
.attr
,
1869 static struct config_item_type uvcg_default_color_matching_type
= {
1870 .ct_item_ops
= &uvcg_default_color_matching_item_ops
,
1871 .ct_attrs
= uvcg_default_color_matching_attrs
,
1872 .ct_owner
= THIS_MODULE
,
1875 /* struct uvcg_color_matching {}; */
1877 static struct config_group
*uvcg_color_matching_default_groups
[] = {
1878 &uvcg_default_color_matching
.group
,
1882 /* streaming/color_matching */
1883 static struct uvcg_color_matching_grp
{
1884 struct config_group group
;
1885 } uvcg_color_matching_grp
;
1887 static struct config_item_type uvcg_color_matching_grp_type
= {
1888 .ct_owner
= THIS_MODULE
,
1891 /* streaming/class/{fs|hs|ss} */
1892 static struct uvcg_streaming_class
{
1893 struct config_group group
;
1894 } uvcg_streaming_class_fs
, uvcg_streaming_class_hs
, uvcg_streaming_class_ss
;
1897 static inline struct uvc_descriptor_header
1898 ***__uvcg_get_stream_class_arr(struct config_item
*i
, struct f_uvc_opts
*o
)
1900 struct uvcg_streaming_class
*cl
= container_of(to_config_group(i
),
1901 struct uvcg_streaming_class
, group
);
1903 if (cl
== &uvcg_streaming_class_fs
)
1904 return &o
->uvc_fs_streaming_cls
;
1906 if (cl
== &uvcg_streaming_class_hs
)
1907 return &o
->uvc_hs_streaming_cls
;
1909 if (cl
== &uvcg_streaming_class_ss
)
1910 return &o
->uvc_ss_streaming_cls
;
1915 enum uvcg_strm_type
{
1922 * Iterate over a hierarchy of streaming descriptors' config items.
1923 * The items are created by the user with configfs.
1925 * It "processes" the header pointed to by @priv1, then for each format
1926 * that follows the header "processes" the format itself and then for
1927 * each frame inside a format "processes" the frame.
1929 * As a "processing" function the @fun is used.
1931 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
1932 * the amount of memory needed for an array of streaming descriptors
1933 * and second, to actually fill the array.
1935 * @h: streaming header pointer
1936 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
1937 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
1938 * @fun: callback function for processing each level of the hierarchy
1940 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header
*h
,
1941 void *priv2
, void *priv3
,
1942 int (*fun
)(void *, void *, void *, int, enum uvcg_strm_type type
))
1944 struct uvcg_format_ptr
*f
;
1945 struct config_group
*grp
;
1946 struct config_item
*item
;
1947 struct uvcg_frame
*frm
;
1954 ret
= fun(h
, priv2
, priv3
, 0, UVCG_HEADER
);
1957 list_for_each_entry(f
, &h
->formats
, entry
) {
1958 ret
= fun(f
->fmt
, priv2
, priv3
, i
++, UVCG_FORMAT
);
1961 grp
= &f
->fmt
->group
;
1962 list_for_each_entry(item
, &grp
->cg_children
, ci_entry
) {
1963 frm
= to_uvcg_frame(item
);
1964 ret
= fun(frm
, priv2
, priv3
, j
++, UVCG_FRAME
);
1974 * Count how many bytes are needed for an array of streaming descriptors.
1976 * @priv1: pointer to a header, format or frame
1977 * @priv2: inout parameter, accumulated size of the array
1978 * @priv3: inout parameter, accumulated number of the array elements
1979 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
1981 static int __uvcg_cnt_strm(void *priv1
, void *priv2
, void *priv3
, int n
,
1982 enum uvcg_strm_type type
)
1984 size_t *size
= priv2
;
1985 size_t *count
= priv3
;
1989 struct uvcg_streaming_header
*h
= priv1
;
1991 *size
+= sizeof(h
->desc
);
1993 *size
+= h
->num_fmt
* UVCG_STREAMING_CONTROL_SIZE
;
1997 struct uvcg_format
*fmt
= priv1
;
1999 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
2000 struct uvcg_uncompressed
*u
=
2001 container_of(fmt
, struct uvcg_uncompressed
,
2004 *size
+= sizeof(u
->desc
);
2005 } else if (fmt
->type
== UVCG_MJPEG
) {
2006 struct uvcg_mjpeg
*m
=
2007 container_of(fmt
, struct uvcg_mjpeg
, fmt
);
2009 *size
+= sizeof(m
->desc
);
2016 struct uvcg_frame
*frm
= priv1
;
2017 int sz
= sizeof(frm
->dw_frame_interval
);
2019 *size
+= sizeof(frm
->frame
);
2020 *size
+= frm
->frame
.b_frame_interval_type
* sz
;
2031 * Fill an array of streaming descriptors.
2033 * @priv1: pointer to a header, format or frame
2034 * @priv2: inout parameter, pointer into a block of memory
2035 * @priv3: inout parameter, pointer to a 2-dimensional array
2037 static int __uvcg_fill_strm(void *priv1
, void *priv2
, void *priv3
, int n
,
2038 enum uvcg_strm_type type
)
2040 void **dest
= priv2
;
2041 struct uvc_descriptor_header
***array
= priv3
;
2049 struct uvc_input_header_descriptor
*ihdr
= *dest
;
2050 struct uvcg_streaming_header
*h
= priv1
;
2051 struct uvcg_format_ptr
*f
;
2053 memcpy(*dest
, &h
->desc
, sizeof(h
->desc
));
2054 *dest
+= sizeof(h
->desc
);
2055 sz
= UVCG_STREAMING_CONTROL_SIZE
;
2056 list_for_each_entry(f
, &h
->formats
, entry
) {
2057 memcpy(*dest
, f
->fmt
->bmaControls
, sz
);
2060 ihdr
->bLength
= sizeof(h
->desc
) + h
->num_fmt
* sz
;
2061 ihdr
->bNumFormats
= h
->num_fmt
;
2065 struct uvcg_format
*fmt
= priv1
;
2067 if (fmt
->type
== UVCG_UNCOMPRESSED
) {
2068 struct uvc_format_uncompressed
*unc
= *dest
;
2069 struct uvcg_uncompressed
*u
=
2070 container_of(fmt
, struct uvcg_uncompressed
,
2073 memcpy(*dest
, &u
->desc
, sizeof(u
->desc
));
2074 *dest
+= sizeof(u
->desc
);
2075 unc
->bNumFrameDescriptors
= fmt
->num_frames
;
2076 unc
->bFormatIndex
= n
+ 1;
2077 } else if (fmt
->type
== UVCG_MJPEG
) {
2078 struct uvc_format_mjpeg
*mjp
= *dest
;
2079 struct uvcg_mjpeg
*m
=
2080 container_of(fmt
, struct uvcg_mjpeg
, fmt
);
2082 memcpy(*dest
, &m
->desc
, sizeof(m
->desc
));
2083 *dest
+= sizeof(m
->desc
);
2084 mjp
->bNumFrameDescriptors
= fmt
->num_frames
;
2085 mjp
->bFormatIndex
= n
+ 1;
2092 struct uvcg_frame
*frm
= priv1
;
2093 struct uvc_descriptor_header
*h
= *dest
;
2095 sz
= sizeof(frm
->frame
);
2096 memcpy(*dest
, &frm
->frame
, sz
);
2098 sz
= frm
->frame
.b_frame_interval_type
*
2099 sizeof(*frm
->dw_frame_interval
);
2100 memcpy(*dest
, frm
->dw_frame_interval
, sz
);
2102 if (frm
->fmt_type
== UVCG_UNCOMPRESSED
)
2103 h
->bLength
= UVC_DT_FRAME_UNCOMPRESSED_SIZE(
2104 frm
->frame
.b_frame_interval_type
);
2105 else if (frm
->fmt_type
== UVCG_MJPEG
)
2106 h
->bLength
= UVC_DT_FRAME_MJPEG_SIZE(
2107 frm
->frame
.b_frame_interval_type
);
2115 static int uvcg_streaming_class_allow_link(struct config_item
*src
,
2116 struct config_item
*target
)
2118 struct config_item
*streaming
, *header
;
2119 struct f_uvc_opts
*opts
;
2120 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
2121 struct uvc_descriptor_header
***class_array
, **cl_arr
;
2122 struct uvcg_streaming_header
*target_hdr
;
2123 void *data
, *data_save
;
2124 size_t size
= 0, count
= 0;
2127 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
2129 streaming
= src
->ci_parent
->ci_parent
;
2130 header
= config_group_find_item(to_config_group(streaming
), "header");
2131 if (!header
|| target
->ci_parent
!= header
)
2134 opts
= to_f_uvc_opts(streaming
->ci_parent
);
2136 mutex_lock(&opts
->lock
);
2138 class_array
= __uvcg_get_stream_class_arr(src
, opts
);
2139 if (!class_array
|| *class_array
|| opts
->refcnt
) {
2144 target_hdr
= to_uvcg_streaming_header(target
);
2145 ret
= __uvcg_iter_strm_cls(target_hdr
, &size
, &count
, __uvcg_cnt_strm
);
2149 count
+= 2; /* color_matching, NULL */
2150 *class_array
= kcalloc(count
, sizeof(void *), GFP_KERNEL
);
2151 if (!*class_array
) {
2156 data
= data_save
= kzalloc(size
, GFP_KERNEL
);
2158 kfree(*class_array
);
2159 *class_array
= NULL
;
2160 ret
= PTR_ERR(data
);
2163 cl_arr
= *class_array
;
2164 ret
= __uvcg_iter_strm_cls(target_hdr
, &data
, &cl_arr
,
2167 kfree(*class_array
);
2168 *class_array
= NULL
;
2170 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2171 * might have advanced the "data", so use a backup copy
2176 *cl_arr
= (struct uvc_descriptor_header
*)&opts
->uvc_color_matching
;
2178 ++target_hdr
->linked
;
2182 mutex_unlock(&opts
->lock
);
2184 mutex_unlock(su_mutex
);
2188 static int uvcg_streaming_class_drop_link(struct config_item
*src
,
2189 struct config_item
*target
)
2191 struct config_item
*streaming
, *header
;
2192 struct f_uvc_opts
*opts
;
2193 struct mutex
*su_mutex
= &src
->ci_group
->cg_subsys
->su_mutex
;
2194 struct uvc_descriptor_header
***class_array
;
2195 struct uvcg_streaming_header
*target_hdr
;
2198 mutex_lock(su_mutex
); /* for navigating configfs hierarchy */
2200 streaming
= src
->ci_parent
->ci_parent
;
2201 header
= config_group_find_item(to_config_group(streaming
), "header");
2202 if (!header
|| target
->ci_parent
!= header
)
2205 opts
= to_f_uvc_opts(streaming
->ci_parent
);
2207 mutex_lock(&opts
->lock
);
2209 class_array
= __uvcg_get_stream_class_arr(src
, opts
);
2210 if (!class_array
|| !*class_array
)
2218 target_hdr
= to_uvcg_streaming_header(target
);
2219 --target_hdr
->linked
;
2220 kfree(**class_array
);
2221 kfree(*class_array
);
2222 *class_array
= NULL
;
2226 mutex_unlock(&opts
->lock
);
2228 mutex_unlock(su_mutex
);
2232 static struct configfs_item_operations uvcg_streaming_class_item_ops
= {
2233 .allow_link
= uvcg_streaming_class_allow_link
,
2234 .drop_link
= uvcg_streaming_class_drop_link
,
2237 static struct config_item_type uvcg_streaming_class_type
= {
2238 .ct_item_ops
= &uvcg_streaming_class_item_ops
,
2239 .ct_owner
= THIS_MODULE
,
2242 static struct config_group
*uvcg_streaming_class_default_groups
[] = {
2243 &uvcg_streaming_class_fs
.group
,
2244 &uvcg_streaming_class_hs
.group
,
2245 &uvcg_streaming_class_ss
.group
,
2249 /* streaming/class */
2250 static struct uvcg_streaming_class_grp
{
2251 struct config_group group
;
2252 } uvcg_streaming_class_grp
;
2254 static struct config_item_type uvcg_streaming_class_grp_type
= {
2255 .ct_owner
= THIS_MODULE
,
2258 static struct config_group
*uvcg_streaming_default_groups
[] = {
2259 &uvcg_streaming_header_grp
.group
,
2260 &uvcg_uncompressed_grp
.group
,
2261 &uvcg_mjpeg_grp
.group
,
2262 &uvcg_color_matching_grp
.group
,
2263 &uvcg_streaming_class_grp
.group
,
2268 static struct uvcg_streaming_grp
{
2269 struct config_group group
;
2270 } uvcg_streaming_grp
;
2272 static struct config_item_type uvcg_streaming_grp_type
= {
2273 .ct_owner
= THIS_MODULE
,
2276 static struct config_group
*uvcg_default_groups
[] = {
2277 &uvcg_control_grp
.group
,
2278 &uvcg_streaming_grp
.group
,
2282 static inline struct f_uvc_opts
*to_f_uvc_opts(struct config_item
*item
)
2284 return container_of(to_config_group(item
), struct f_uvc_opts
,
2288 CONFIGFS_ATTR_STRUCT(f_uvc_opts
);
2289 CONFIGFS_ATTR_OPS(f_uvc_opts
);
2291 static void uvc_attr_release(struct config_item
*item
)
2293 struct f_uvc_opts
*opts
= to_f_uvc_opts(item
);
2295 usb_put_function_instance(&opts
->func_inst
);
2298 static struct configfs_item_operations uvc_item_ops
= {
2299 .release
= uvc_attr_release
,
2300 .show_attribute
= f_uvc_opts_attr_show
,
2301 .store_attribute
= f_uvc_opts_attr_store
,
2304 #define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \
2305 static ssize_t f_uvc_opts_##cname##_show( \
2306 struct f_uvc_opts *opts, char *page) \
2310 mutex_lock(&opts->lock); \
2311 result = sprintf(page, "%d\n", conv(opts->cname)); \
2312 mutex_unlock(&opts->lock); \
2318 f_uvc_opts_##cname##_store(struct f_uvc_opts *opts, \
2319 const char *page, size_t len) \
2324 mutex_lock(&opts->lock); \
2325 if (opts->refcnt) { \
2330 ret = str2u(page, 0, &num); \
2334 if (num > limit) { \
2338 opts->cname = vnoc(num); \
2341 mutex_unlock(&opts->lock); \
2345 static struct f_uvc_opts_attribute \
2346 f_uvc_opts_attribute_##cname = \
2347 __CONFIGFS_ATTR(cname, S_IRUGO | S_IWUSR, \
2348 f_uvc_opts_##cname##_show, \
2349 f_uvc_opts_##cname##_store)
2351 #define identity_conv(x) (x)
2353 UVCG_OPTS_ATTR(streaming_interval
, identity_conv
, kstrtou8
, u8
, identity_conv
,
2355 UVCG_OPTS_ATTR(streaming_maxpacket
, le16_to_cpu
, kstrtou16
, u16
, le16_to_cpu
,
2357 UVCG_OPTS_ATTR(streaming_maxburst
, identity_conv
, kstrtou8
, u8
, identity_conv
,
2360 #undef identity_conv
2362 #undef UVCG_OPTS_ATTR
2364 static struct configfs_attribute
*uvc_attrs
[] = {
2365 &f_uvc_opts_attribute_streaming_interval
.attr
,
2366 &f_uvc_opts_attribute_streaming_maxpacket
.attr
,
2367 &f_uvc_opts_attribute_streaming_maxburst
.attr
,
2371 static struct config_item_type uvc_func_type
= {
2372 .ct_item_ops
= &uvc_item_ops
,
2373 .ct_attrs
= uvc_attrs
,
2374 .ct_owner
= THIS_MODULE
,
2377 static inline void uvcg_init_group(struct config_group
*g
,
2378 struct config_group
**default_groups
,
2380 struct config_item_type
*type
)
2382 g
->default_groups
= default_groups
;
2383 config_group_init_type_name(g
, name
, type
);
2386 int uvcg_attach_configfs(struct f_uvc_opts
*opts
)
2388 config_group_init_type_name(&uvcg_control_header_grp
.group
,
2390 &uvcg_control_header_grp_type
);
2391 config_group_init_type_name(&uvcg_default_processing
.group
,
2393 &uvcg_default_processing_type
);
2394 uvcg_init_group(&uvcg_processing_grp
.group
,
2395 uvcg_processing_default_groups
,
2397 &uvcg_processing_grp_type
);
2398 config_group_init_type_name(&uvcg_default_camera
.group
,
2400 &uvcg_default_camera_type
);
2401 uvcg_init_group(&uvcg_camera_grp
.group
,
2402 uvcg_camera_default_groups
,
2404 &uvcg_camera_grp_type
);
2405 config_group_init_type_name(&uvcg_default_output
.group
,
2407 &uvcg_default_output_type
);
2408 uvcg_init_group(&uvcg_output_grp
.group
,
2409 uvcg_output_default_groups
,
2411 &uvcg_output_grp_type
);
2412 uvcg_init_group(&uvcg_terminal_grp
.group
,
2413 uvcg_terminal_default_groups
,
2415 &uvcg_terminal_grp_type
);
2416 config_group_init_type_name(&uvcg_control_class_fs
.group
,
2418 &uvcg_control_class_type
);
2419 config_group_init_type_name(&uvcg_control_class_ss
.group
,
2421 &uvcg_control_class_type
);
2422 uvcg_init_group(&uvcg_control_class_grp
.group
,
2423 uvcg_control_class_default_groups
,
2425 &uvcg_control_class_grp_type
);
2426 uvcg_init_group(&uvcg_control_grp
.group
,
2427 uvcg_control_default_groups
,
2429 &uvcg_control_grp_type
);
2430 config_group_init_type_name(&uvcg_streaming_header_grp
.group
,
2432 &uvcg_streaming_header_grp_type
);
2433 config_group_init_type_name(&uvcg_uncompressed_grp
.group
,
2435 &uvcg_uncompressed_grp_type
);
2436 config_group_init_type_name(&uvcg_mjpeg_grp
.group
,
2438 &uvcg_mjpeg_grp_type
);
2439 config_group_init_type_name(&uvcg_default_color_matching
.group
,
2441 &uvcg_default_color_matching_type
);
2442 uvcg_init_group(&uvcg_color_matching_grp
.group
,
2443 uvcg_color_matching_default_groups
,
2445 &uvcg_color_matching_grp_type
);
2446 config_group_init_type_name(&uvcg_streaming_class_fs
.group
,
2448 &uvcg_streaming_class_type
);
2449 config_group_init_type_name(&uvcg_streaming_class_hs
.group
,
2451 &uvcg_streaming_class_type
);
2452 config_group_init_type_name(&uvcg_streaming_class_ss
.group
,
2454 &uvcg_streaming_class_type
);
2455 uvcg_init_group(&uvcg_streaming_class_grp
.group
,
2456 uvcg_streaming_class_default_groups
,
2458 &uvcg_streaming_class_grp_type
);
2459 uvcg_init_group(&uvcg_streaming_grp
.group
,
2460 uvcg_streaming_default_groups
,
2462 &uvcg_streaming_grp_type
);
2463 uvcg_init_group(&opts
->func_inst
.group
,
2464 uvcg_default_groups
,