1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * uvc_configfs.c
4 *
5 * Configfs support for the uvc function.
6 *
7 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
8 * http://www.samsung.com
9 *
10 * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
11 */
12
13 #include <linux/sort.h>
14
15 #include "u_uvc.h"
16 #include "uvc_configfs.h"
17
18 /* -----------------------------------------------------------------------------
19 * Global Utility Structures and Macros
20 */
21
22 #define UVCG_STREAMING_CONTROL_SIZE 1
23
24 #define UVC_ATTR(prefix, cname, aname) \
25 static struct configfs_attribute prefix##attr_##cname = { \
26 .ca_name = __stringify(aname), \
27 .ca_mode = S_IRUGO | S_IWUGO, \
28 .ca_owner = THIS_MODULE, \
29 .show = prefix##cname##_show, \
30 .store = prefix##cname##_store, \
31 }
32
33 #define UVC_ATTR_RO(prefix, cname, aname) \
34 static struct configfs_attribute prefix##attr_##cname = { \
35 .ca_name = __stringify(aname), \
36 .ca_mode = S_IRUGO, \
37 .ca_owner = THIS_MODULE, \
38 .show = prefix##cname##_show, \
39 }
40
41 #define le8_to_cpu(x) (x)
42 #define cpu_to_le8(x) (x)
43
uvcg_config_compare_u32(const void * l,const void * r)44 static int uvcg_config_compare_u32(const void *l, const void *r)
45 {
46 u32 li = *(const u32 *)l;
47 u32 ri = *(const u32 *)r;
48
49 return li < ri ? -1 : li == ri ? 0 : 1;
50 }
51
to_f_uvc_opts(struct config_item * item)52 static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
53 {
54 return container_of(to_config_group(item), struct f_uvc_opts,
55 func_inst.group);
56 }
57
58 struct uvcg_config_group_type {
59 struct config_item_type type;
60 const char *name;
61 const struct uvcg_config_group_type **children;
62 int (*create_children)(struct config_group *group);
63 };
64
uvcg_config_item_release(struct config_item * item)65 static void uvcg_config_item_release(struct config_item *item)
66 {
67 struct config_group *group = to_config_group(item);
68
69 kfree(group);
70 }
71
72 static struct configfs_item_operations uvcg_config_item_ops = {
73 .release = uvcg_config_item_release,
74 };
75
76 static int uvcg_config_create_group(struct config_group *parent,
77 const struct uvcg_config_group_type *type);
78
uvcg_config_create_children(struct config_group * group,const struct uvcg_config_group_type * type)79 static int uvcg_config_create_children(struct config_group *group,
80 const struct uvcg_config_group_type *type)
81 {
82 const struct uvcg_config_group_type **child;
83 int ret;
84
85 if (type->create_children)
86 return type->create_children(group);
87
88 for (child = type->children; child && *child; ++child) {
89 ret = uvcg_config_create_group(group, *child);
90 if (ret < 0)
91 return ret;
92 }
93
94 return 0;
95 }
96
uvcg_config_create_group(struct config_group * parent,const struct uvcg_config_group_type * type)97 static int uvcg_config_create_group(struct config_group *parent,
98 const struct uvcg_config_group_type *type)
99 {
100 struct config_group *group;
101
102 group = kzalloc(sizeof(*group), GFP_KERNEL);
103 if (!group)
104 return -ENOMEM;
105
106 config_group_init_type_name(group, type->name, &type->type);
107 configfs_add_default_group(group, parent);
108
109 return uvcg_config_create_children(group, type);
110 }
111
uvcg_config_remove_children(struct config_group * group)112 static void uvcg_config_remove_children(struct config_group *group)
113 {
114 struct config_group *child, *n;
115
116 list_for_each_entry_safe(child, n, &group->default_groups, group_entry) {
117 list_del(&child->group_entry);
118 uvcg_config_remove_children(child);
119 config_item_put(&child->cg_item);
120 }
121 }
122
123 /* -----------------------------------------------------------------------------
124 * control/header/<NAME>
125 * control/header
126 */
127
128 DECLARE_UVC_HEADER_DESCRIPTOR(1);
129
130 struct uvcg_control_header {
131 struct config_item item;
132 struct UVC_HEADER_DESCRIPTOR(1) desc;
133 unsigned linked;
134 };
135
to_uvcg_control_header(struct config_item * item)136 static struct uvcg_control_header *to_uvcg_control_header(struct config_item *item)
137 {
138 return container_of(item, struct uvcg_control_header, item);
139 }
140
141 #define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \
142 static ssize_t uvcg_control_header_##cname##_show( \
143 struct config_item *item, char *page) \
144 { \
145 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
146 struct f_uvc_opts *opts; \
147 struct config_item *opts_item; \
148 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
149 int result; \
150 \
151 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
152 \
153 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
154 opts = to_f_uvc_opts(opts_item); \
155 \
156 mutex_lock(&opts->lock); \
157 result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\
158 mutex_unlock(&opts->lock); \
159 \
160 mutex_unlock(su_mutex); \
161 return result; \
162 } \
163 \
164 static ssize_t \
165 uvcg_control_header_##cname##_store(struct config_item *item, \
166 const char *page, size_t len) \
167 { \
168 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
169 struct f_uvc_opts *opts; \
170 struct config_item *opts_item; \
171 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
172 int ret; \
173 u##bits num; \
174 \
175 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
176 \
177 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
178 opts = to_f_uvc_opts(opts_item); \
179 \
180 mutex_lock(&opts->lock); \
181 if (ch->linked || opts->refcnt) { \
182 ret = -EBUSY; \
183 goto end; \
184 } \
185 \
186 ret = kstrtou##bits(page, 0, &num); \
187 if (ret) \
188 goto end; \
189 \
190 if (num > limit) { \
191 ret = -EINVAL; \
192 goto end; \
193 } \
194 ch->desc.aname = cpu_to_le##bits(num); \
195 ret = len; \
196 end: \
197 mutex_unlock(&opts->lock); \
198 mutex_unlock(su_mutex); \
199 return ret; \
200 } \
201 \
202 UVC_ATTR(uvcg_control_header_, cname, aname)
203
204 UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, 16, 0xffff);
205
206 UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, 32, 0x7fffffff);
207
208 #undef UVCG_CTRL_HDR_ATTR
209
210 static struct configfs_attribute *uvcg_control_header_attrs[] = {
211 &uvcg_control_header_attr_bcd_uvc,
212 &uvcg_control_header_attr_dw_clock_frequency,
213 NULL,
214 };
215
216 static const struct config_item_type uvcg_control_header_type = {
217 .ct_item_ops = &uvcg_config_item_ops,
218 .ct_attrs = uvcg_control_header_attrs,
219 .ct_owner = THIS_MODULE,
220 };
221
uvcg_control_header_make(struct config_group * group,const char * name)222 static struct config_item *uvcg_control_header_make(struct config_group *group,
223 const char *name)
224 {
225 struct uvcg_control_header *h;
226
227 h = kzalloc(sizeof(*h), GFP_KERNEL);
228 if (!h)
229 return ERR_PTR(-ENOMEM);
230
231 h->desc.bLength = UVC_DT_HEADER_SIZE(1);
232 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
233 h->desc.bDescriptorSubType = UVC_VC_HEADER;
234 h->desc.bcdUVC = cpu_to_le16(0x0100);
235 h->desc.dwClockFrequency = cpu_to_le32(48000000);
236
237 config_item_init_type_name(&h->item, name, &uvcg_control_header_type);
238
239 return &h->item;
240 }
241
242 static struct configfs_group_operations uvcg_control_header_grp_ops = {
243 .make_item = uvcg_control_header_make,
244 };
245
246 static const struct uvcg_config_group_type uvcg_control_header_grp_type = {
247 .type = {
248 .ct_item_ops = &uvcg_config_item_ops,
249 .ct_group_ops = &uvcg_control_header_grp_ops,
250 .ct_owner = THIS_MODULE,
251 },
252 .name = "header",
253 };
254
255 /* -----------------------------------------------------------------------------
256 * control/processing/default
257 */
258
259 #define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, bits) \
260 static ssize_t uvcg_default_processing_##cname##_show( \
261 struct config_item *item, char *page) \
262 { \
263 struct config_group *group = to_config_group(item); \
264 struct f_uvc_opts *opts; \
265 struct config_item *opts_item; \
266 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
267 struct uvc_processing_unit_descriptor *pd; \
268 int result; \
269 \
270 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
271 \
272 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
273 opts = to_f_uvc_opts(opts_item); \
274 pd = &opts->uvc_processing; \
275 \
276 mutex_lock(&opts->lock); \
277 result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \
278 mutex_unlock(&opts->lock); \
279 \
280 mutex_unlock(su_mutex); \
281 return result; \
282 } \
283 \
284 UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
285
286 UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, 8);
287 UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, 8);
288 UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, 16);
289 UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8);
290
291 #undef UVCG_DEFAULT_PROCESSING_ATTR
292
uvcg_default_processing_bm_controls_show(struct config_item * item,char * page)293 static ssize_t uvcg_default_processing_bm_controls_show(
294 struct config_item *item, char *page)
295 {
296 struct config_group *group = to_config_group(item);
297 struct f_uvc_opts *opts;
298 struct config_item *opts_item;
299 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
300 struct uvc_processing_unit_descriptor *pd;
301 int result, i;
302 char *pg = page;
303
304 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
305
306 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
307 opts = to_f_uvc_opts(opts_item);
308 pd = &opts->uvc_processing;
309
310 mutex_lock(&opts->lock);
311 for (result = 0, i = 0; i < pd->bControlSize; ++i) {
312 result += sprintf(pg, "%u\n", pd->bmControls[i]);
313 pg = page + result;
314 }
315 mutex_unlock(&opts->lock);
316
317 mutex_unlock(su_mutex);
318
319 return result;
320 }
321
322 UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
323
324 static struct configfs_attribute *uvcg_default_processing_attrs[] = {
325 &uvcg_default_processing_attr_b_unit_id,
326 &uvcg_default_processing_attr_b_source_id,
327 &uvcg_default_processing_attr_w_max_multiplier,
328 &uvcg_default_processing_attr_bm_controls,
329 &uvcg_default_processing_attr_i_processing,
330 NULL,
331 };
332
333 static const struct uvcg_config_group_type uvcg_default_processing_type = {
334 .type = {
335 .ct_item_ops = &uvcg_config_item_ops,
336 .ct_attrs = uvcg_default_processing_attrs,
337 .ct_owner = THIS_MODULE,
338 },
339 .name = "default",
340 };
341
342 /* -----------------------------------------------------------------------------
343 * control/processing
344 */
345
346 static const struct uvcg_config_group_type uvcg_processing_grp_type = {
347 .type = {
348 .ct_item_ops = &uvcg_config_item_ops,
349 .ct_owner = THIS_MODULE,
350 },
351 .name = "processing",
352 .children = (const struct uvcg_config_group_type*[]) {
353 &uvcg_default_processing_type,
354 NULL,
355 },
356 };
357
358 /* -----------------------------------------------------------------------------
359 * control/terminal/camera/default
360 */
361
362 #define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, bits) \
363 static ssize_t uvcg_default_camera_##cname##_show( \
364 struct config_item *item, char *page) \
365 { \
366 struct config_group *group = to_config_group(item); \
367 struct f_uvc_opts *opts; \
368 struct config_item *opts_item; \
369 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
370 struct uvc_camera_terminal_descriptor *cd; \
371 int result; \
372 \
373 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
374 \
375 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \
376 ci_parent; \
377 opts = to_f_uvc_opts(opts_item); \
378 cd = &opts->uvc_camera_terminal; \
379 \
380 mutex_lock(&opts->lock); \
381 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
382 mutex_unlock(&opts->lock); \
383 \
384 mutex_unlock(su_mutex); \
385 \
386 return result; \
387 } \
388 \
389 UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
390
391 UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, 8);
392 UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, 16);
393 UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, 8);
394 UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, 8);
395 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
396 16);
397 UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
398 16);
399 UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
400 16);
401
402 #undef UVCG_DEFAULT_CAMERA_ATTR
403
uvcg_default_camera_bm_controls_show(struct config_item * item,char * page)404 static ssize_t uvcg_default_camera_bm_controls_show(
405 struct config_item *item, char *page)
406 {
407 struct config_group *group = to_config_group(item);
408 struct f_uvc_opts *opts;
409 struct config_item *opts_item;
410 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
411 struct uvc_camera_terminal_descriptor *cd;
412 int result, i;
413 char *pg = page;
414
415 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
416
417 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
418 ci_parent;
419 opts = to_f_uvc_opts(opts_item);
420 cd = &opts->uvc_camera_terminal;
421
422 mutex_lock(&opts->lock);
423 for (result = 0, i = 0; i < cd->bControlSize; ++i) {
424 result += sprintf(pg, "%u\n", cd->bmControls[i]);
425 pg = page + result;
426 }
427 mutex_unlock(&opts->lock);
428
429 mutex_unlock(su_mutex);
430 return result;
431 }
432
433 UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
434
435 static struct configfs_attribute *uvcg_default_camera_attrs[] = {
436 &uvcg_default_camera_attr_b_terminal_id,
437 &uvcg_default_camera_attr_w_terminal_type,
438 &uvcg_default_camera_attr_b_assoc_terminal,
439 &uvcg_default_camera_attr_i_terminal,
440 &uvcg_default_camera_attr_w_objective_focal_length_min,
441 &uvcg_default_camera_attr_w_objective_focal_length_max,
442 &uvcg_default_camera_attr_w_ocular_focal_length,
443 &uvcg_default_camera_attr_bm_controls,
444 NULL,
445 };
446
447 static const struct uvcg_config_group_type uvcg_default_camera_type = {
448 .type = {
449 .ct_item_ops = &uvcg_config_item_ops,
450 .ct_attrs = uvcg_default_camera_attrs,
451 .ct_owner = THIS_MODULE,
452 },
453 .name = "default",
454 };
455
456 /* -----------------------------------------------------------------------------
457 * control/terminal/camera
458 */
459
460 static const struct uvcg_config_group_type uvcg_camera_grp_type = {
461 .type = {
462 .ct_item_ops = &uvcg_config_item_ops,
463 .ct_owner = THIS_MODULE,
464 },
465 .name = "camera",
466 .children = (const struct uvcg_config_group_type*[]) {
467 &uvcg_default_camera_type,
468 NULL,
469 },
470 };
471
472 /* -----------------------------------------------------------------------------
473 * control/terminal/output/default
474 */
475
476 #define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, bits) \
477 static ssize_t uvcg_default_output_##cname##_show( \
478 struct config_item *item, char *page) \
479 { \
480 struct config_group *group = to_config_group(item); \
481 struct f_uvc_opts *opts; \
482 struct config_item *opts_item; \
483 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
484 struct uvc_output_terminal_descriptor *cd; \
485 int result; \
486 \
487 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
488 \
489 opts_item = group->cg_item.ci_parent->ci_parent-> \
490 ci_parent->ci_parent; \
491 opts = to_f_uvc_opts(opts_item); \
492 cd = &opts->uvc_output_terminal; \
493 \
494 mutex_lock(&opts->lock); \
495 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
496 mutex_unlock(&opts->lock); \
497 \
498 mutex_unlock(su_mutex); \
499 \
500 return result; \
501 } \
502 \
503 UVC_ATTR_RO(uvcg_default_output_, cname, aname)
504
505 UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, 8);
506 UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, 16);
507 UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, 8);
508 UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, 8);
509
510 #undef UVCG_DEFAULT_OUTPUT_ATTR
511
uvcg_default_output_b_source_id_show(struct config_item * item,char * page)512 static ssize_t uvcg_default_output_b_source_id_show(struct config_item *item,
513 char *page)
514 {
515 struct config_group *group = to_config_group(item);
516 struct f_uvc_opts *opts;
517 struct config_item *opts_item;
518 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
519 struct uvc_output_terminal_descriptor *cd;
520 int result;
521
522 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
523
524 opts_item = group->cg_item.ci_parent->ci_parent->
525 ci_parent->ci_parent;
526 opts = to_f_uvc_opts(opts_item);
527 cd = &opts->uvc_output_terminal;
528
529 mutex_lock(&opts->lock);
530 result = sprintf(page, "%u\n", le8_to_cpu(cd->bSourceID));
531 mutex_unlock(&opts->lock);
532
533 mutex_unlock(su_mutex);
534
535 return result;
536 }
537
uvcg_default_output_b_source_id_store(struct config_item * item,const char * page,size_t len)538 static ssize_t uvcg_default_output_b_source_id_store(struct config_item *item,
539 const char *page, size_t len)
540 {
541 struct config_group *group = to_config_group(item);
542 struct f_uvc_opts *opts;
543 struct config_item *opts_item;
544 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
545 struct uvc_output_terminal_descriptor *cd;
546 int result;
547 u8 num;
548
549 result = kstrtou8(page, 0, &num);
550 if (result)
551 return result;
552
553 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
554
555 opts_item = group->cg_item.ci_parent->ci_parent->
556 ci_parent->ci_parent;
557 opts = to_f_uvc_opts(opts_item);
558 cd = &opts->uvc_output_terminal;
559
560 mutex_lock(&opts->lock);
561 cd->bSourceID = num;
562 mutex_unlock(&opts->lock);
563
564 mutex_unlock(su_mutex);
565
566 return len;
567 }
568 UVC_ATTR(uvcg_default_output_, b_source_id, bSourceID);
569
570 static struct configfs_attribute *uvcg_default_output_attrs[] = {
571 &uvcg_default_output_attr_b_terminal_id,
572 &uvcg_default_output_attr_w_terminal_type,
573 &uvcg_default_output_attr_b_assoc_terminal,
574 &uvcg_default_output_attr_b_source_id,
575 &uvcg_default_output_attr_i_terminal,
576 NULL,
577 };
578
579 static const struct uvcg_config_group_type uvcg_default_output_type = {
580 .type = {
581 .ct_item_ops = &uvcg_config_item_ops,
582 .ct_attrs = uvcg_default_output_attrs,
583 .ct_owner = THIS_MODULE,
584 },
585 .name = "default",
586 };
587
588 /* -----------------------------------------------------------------------------
589 * control/terminal/output
590 */
591
592 static const struct uvcg_config_group_type uvcg_output_grp_type = {
593 .type = {
594 .ct_item_ops = &uvcg_config_item_ops,
595 .ct_owner = THIS_MODULE,
596 },
597 .name = "output",
598 .children = (const struct uvcg_config_group_type*[]) {
599 &uvcg_default_output_type,
600 NULL,
601 },
602 };
603
604 /* -----------------------------------------------------------------------------
605 * control/terminal
606 */
607
608 static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
609 .type = {
610 .ct_item_ops = &uvcg_config_item_ops,
611 .ct_owner = THIS_MODULE,
612 },
613 .name = "terminal",
614 .children = (const struct uvcg_config_group_type*[]) {
615 &uvcg_camera_grp_type,
616 &uvcg_output_grp_type,
617 NULL,
618 },
619 };
620
621 /* -----------------------------------------------------------------------------
622 * control/class/{fs|ss}
623 */
624
625 struct uvcg_control_class_group {
626 struct config_group group;
627 const char *name;
628 };
629
630 static inline struct uvc_descriptor_header
uvcg_get_ctl_class_arr(struct config_item * i,struct f_uvc_opts * o)631 **uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
632 {
633 struct uvcg_control_class_group *group =
634 container_of(i, struct uvcg_control_class_group,
635 group.cg_item);
636
637 if (!strcmp(group->name, "fs"))
638 return o->uvc_fs_control_cls;
639
640 if (!strcmp(group->name, "ss"))
641 return o->uvc_ss_control_cls;
642
643 return NULL;
644 }
645
uvcg_control_class_allow_link(struct config_item * src,struct config_item * target)646 static int uvcg_control_class_allow_link(struct config_item *src,
647 struct config_item *target)
648 {
649 struct config_item *control, *header;
650 struct f_uvc_opts *opts;
651 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
652 struct uvc_descriptor_header **class_array;
653 struct uvcg_control_header *target_hdr;
654 int ret = -EINVAL;
655
656 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
657
658 control = src->ci_parent->ci_parent;
659 header = config_group_find_item(to_config_group(control), "header");
660 if (!header || target->ci_parent != header)
661 goto out;
662
663 opts = to_f_uvc_opts(control->ci_parent);
664
665 mutex_lock(&opts->lock);
666
667 class_array = uvcg_get_ctl_class_arr(src, opts);
668 if (!class_array)
669 goto unlock;
670 if (opts->refcnt || class_array[0]) {
671 ret = -EBUSY;
672 goto unlock;
673 }
674
675 target_hdr = to_uvcg_control_header(target);
676 ++target_hdr->linked;
677 class_array[0] = (struct uvc_descriptor_header *)&target_hdr->desc;
678 ret = 0;
679
680 unlock:
681 mutex_unlock(&opts->lock);
682 out:
683 config_item_put(header);
684 mutex_unlock(su_mutex);
685 return ret;
686 }
687
uvcg_control_class_drop_link(struct config_item * src,struct config_item * target)688 static void uvcg_control_class_drop_link(struct config_item *src,
689 struct config_item *target)
690 {
691 struct config_item *control, *header;
692 struct f_uvc_opts *opts;
693 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
694 struct uvc_descriptor_header **class_array;
695 struct uvcg_control_header *target_hdr;
696
697 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
698
699 control = src->ci_parent->ci_parent;
700 header = config_group_find_item(to_config_group(control), "header");
701 if (!header || target->ci_parent != header)
702 goto out;
703
704 opts = to_f_uvc_opts(control->ci_parent);
705
706 mutex_lock(&opts->lock);
707
708 class_array = uvcg_get_ctl_class_arr(src, opts);
709 if (!class_array || opts->refcnt)
710 goto unlock;
711
712 target_hdr = to_uvcg_control_header(target);
713 --target_hdr->linked;
714 class_array[0] = NULL;
715
716 unlock:
717 mutex_unlock(&opts->lock);
718 out:
719 config_item_put(header);
720 mutex_unlock(su_mutex);
721 }
722
723 static struct configfs_item_operations uvcg_control_class_item_ops = {
724 .release = uvcg_config_item_release,
725 .allow_link = uvcg_control_class_allow_link,
726 .drop_link = uvcg_control_class_drop_link,
727 };
728
729 static const struct config_item_type uvcg_control_class_type = {
730 .ct_item_ops = &uvcg_control_class_item_ops,
731 .ct_owner = THIS_MODULE,
732 };
733
734 /* -----------------------------------------------------------------------------
735 * control/class
736 */
737
uvcg_control_class_create_children(struct config_group * parent)738 static int uvcg_control_class_create_children(struct config_group *parent)
739 {
740 static const char * const names[] = { "fs", "ss" };
741 unsigned int i;
742
743 for (i = 0; i < ARRAY_SIZE(names); ++i) {
744 struct uvcg_control_class_group *group;
745
746 group = kzalloc(sizeof(*group), GFP_KERNEL);
747 if (!group)
748 return -ENOMEM;
749
750 group->name = names[i];
751
752 config_group_init_type_name(&group->group, group->name,
753 &uvcg_control_class_type);
754 configfs_add_default_group(&group->group, parent);
755 }
756
757 return 0;
758 }
759
760 static const struct uvcg_config_group_type uvcg_control_class_grp_type = {
761 .type = {
762 .ct_item_ops = &uvcg_config_item_ops,
763 .ct_owner = THIS_MODULE,
764 },
765 .name = "class",
766 .create_children = uvcg_control_class_create_children,
767 };
768
769 /* -----------------------------------------------------------------------------
770 * control
771 */
772
uvcg_default_control_b_interface_number_show(struct config_item * item,char * page)773 static ssize_t uvcg_default_control_b_interface_number_show(
774 struct config_item *item, char *page)
775 {
776 struct config_group *group = to_config_group(item);
777 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
778 struct config_item *opts_item;
779 struct f_uvc_opts *opts;
780 int result = 0;
781
782 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
783
784 opts_item = item->ci_parent;
785 opts = to_f_uvc_opts(opts_item);
786
787 mutex_lock(&opts->lock);
788 result += sprintf(page, "%u\n", opts->control_interface);
789 mutex_unlock(&opts->lock);
790
791 mutex_unlock(su_mutex);
792
793 return result;
794 }
795
796 UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
797
798 static struct configfs_attribute *uvcg_default_control_attrs[] = {
799 &uvcg_default_control_attr_b_interface_number,
800 NULL,
801 };
802
803 static const struct uvcg_config_group_type uvcg_control_grp_type = {
804 .type = {
805 .ct_item_ops = &uvcg_config_item_ops,
806 .ct_attrs = uvcg_default_control_attrs,
807 .ct_owner = THIS_MODULE,
808 },
809 .name = "control",
810 .children = (const struct uvcg_config_group_type*[]) {
811 &uvcg_control_header_grp_type,
812 &uvcg_processing_grp_type,
813 &uvcg_terminal_grp_type,
814 &uvcg_control_class_grp_type,
815 NULL,
816 },
817 };
818
819 /* -----------------------------------------------------------------------------
820 * streaming/uncompressed
821 * streaming/mjpeg
822 */
823
824 static const char * const uvcg_format_names[] = {
825 "uncompressed",
826 "mjpeg",
827 };
828
829 enum uvcg_format_type {
830 UVCG_UNCOMPRESSED = 0,
831 UVCG_MJPEG,
832 };
833
834 struct uvcg_format {
835 struct config_group group;
836 enum uvcg_format_type type;
837 unsigned linked;
838 unsigned num_frames;
839 __u8 bmaControls[UVCG_STREAMING_CONTROL_SIZE];
840 };
841
to_uvcg_format(struct config_item * item)842 static struct uvcg_format *to_uvcg_format(struct config_item *item)
843 {
844 return container_of(to_config_group(item), struct uvcg_format, group);
845 }
846
uvcg_format_bma_controls_show(struct uvcg_format * f,char * page)847 static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
848 {
849 struct f_uvc_opts *opts;
850 struct config_item *opts_item;
851 struct mutex *su_mutex = &f->group.cg_subsys->su_mutex;
852 int result, i;
853 char *pg = page;
854
855 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
856
857 opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
858 opts = to_f_uvc_opts(opts_item);
859
860 mutex_lock(&opts->lock);
861 result = sprintf(pg, "0x");
862 pg += result;
863 for (i = 0; i < UVCG_STREAMING_CONTROL_SIZE; ++i) {
864 result += sprintf(pg, "%x\n", f->bmaControls[i]);
865 pg = page + result;
866 }
867 mutex_unlock(&opts->lock);
868
869 mutex_unlock(su_mutex);
870 return result;
871 }
872
uvcg_format_bma_controls_store(struct uvcg_format * ch,const char * page,size_t len)873 static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
874 const char *page, size_t len)
875 {
876 struct f_uvc_opts *opts;
877 struct config_item *opts_item;
878 struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex;
879 int ret = -EINVAL;
880
881 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
882
883 opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent;
884 opts = to_f_uvc_opts(opts_item);
885
886 mutex_lock(&opts->lock);
887 if (ch->linked || opts->refcnt) {
888 ret = -EBUSY;
889 goto end;
890 }
891
892 if (len < 4 || *page != '0' ||
893 (*(page + 1) != 'x' && *(page + 1) != 'X'))
894 goto end;
895 ret = hex2bin(ch->bmaControls, page + 2, 1);
896 if (ret < 0)
897 goto end;
898 ret = len;
899 end:
900 mutex_unlock(&opts->lock);
901 mutex_unlock(su_mutex);
902 return ret;
903 }
904
905 struct uvcg_format_ptr {
906 struct uvcg_format *fmt;
907 struct list_head entry;
908 };
909
910 /* -----------------------------------------------------------------------------
911 * streaming/header/<NAME>
912 * streaming/header
913 */
914
915 struct uvcg_streaming_header {
916 struct config_item item;
917 struct uvc_input_header_descriptor desc;
918 unsigned linked;
919 struct list_head formats;
920 unsigned num_fmt;
921 };
922
to_uvcg_streaming_header(struct config_item * item)923 static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item *item)
924 {
925 return container_of(item, struct uvcg_streaming_header, item);
926 }
927
928 static void uvcg_format_set_indices(struct config_group *fmt);
929
uvcg_streaming_header_allow_link(struct config_item * src,struct config_item * target)930 static int uvcg_streaming_header_allow_link(struct config_item *src,
931 struct config_item *target)
932 {
933 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
934 struct config_item *opts_item;
935 struct f_uvc_opts *opts;
936 struct uvcg_streaming_header *src_hdr;
937 struct uvcg_format *target_fmt = NULL;
938 struct uvcg_format_ptr *format_ptr;
939 int i, ret = -EINVAL;
940
941 src_hdr = to_uvcg_streaming_header(src);
942 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
943
944 opts_item = src->ci_parent->ci_parent->ci_parent;
945 opts = to_f_uvc_opts(opts_item);
946
947 mutex_lock(&opts->lock);
948
949 if (src_hdr->linked) {
950 ret = -EBUSY;
951 goto out;
952 }
953
954 /*
955 * Linking is only allowed to direct children of the format nodes
956 * (streaming/uncompressed or streaming/mjpeg nodes). First check that
957 * the grand-parent of the target matches the grand-parent of the source
958 * (the streaming node), and then verify that the target parent is a
959 * format node.
960 */
961 if (src->ci_parent->ci_parent != target->ci_parent->ci_parent)
962 goto out;
963
964 for (i = 0; i < ARRAY_SIZE(uvcg_format_names); ++i) {
965 if (!strcmp(target->ci_parent->ci_name, uvcg_format_names[i]))
966 break;
967 }
968
969 if (i == ARRAY_SIZE(uvcg_format_names))
970 goto out;
971
972 target_fmt = container_of(to_config_group(target), struct uvcg_format,
973 group);
974 if (!target_fmt)
975 goto out;
976
977 uvcg_format_set_indices(to_config_group(target));
978
979 format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
980 if (!format_ptr) {
981 ret = -ENOMEM;
982 goto out;
983 }
984 ret = 0;
985 format_ptr->fmt = target_fmt;
986 list_add_tail(&format_ptr->entry, &src_hdr->formats);
987 ++src_hdr->num_fmt;
988 ++target_fmt->linked;
989
990 out:
991 mutex_unlock(&opts->lock);
992 mutex_unlock(su_mutex);
993 return ret;
994 }
995
uvcg_streaming_header_drop_link(struct config_item * src,struct config_item * target)996 static void uvcg_streaming_header_drop_link(struct config_item *src,
997 struct config_item *target)
998 {
999 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1000 struct config_item *opts_item;
1001 struct f_uvc_opts *opts;
1002 struct uvcg_streaming_header *src_hdr;
1003 struct uvcg_format *target_fmt = NULL;
1004 struct uvcg_format_ptr *format_ptr, *tmp;
1005
1006 src_hdr = to_uvcg_streaming_header(src);
1007 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1008
1009 opts_item = src->ci_parent->ci_parent->ci_parent;
1010 opts = to_f_uvc_opts(opts_item);
1011
1012 mutex_lock(&opts->lock);
1013 target_fmt = container_of(to_config_group(target), struct uvcg_format,
1014 group);
1015 if (!target_fmt)
1016 goto out;
1017
1018 list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
1019 if (format_ptr->fmt == target_fmt) {
1020 list_del(&format_ptr->entry);
1021 kfree(format_ptr);
1022 --src_hdr->num_fmt;
1023 break;
1024 }
1025
1026 --target_fmt->linked;
1027
1028 out:
1029 mutex_unlock(&opts->lock);
1030 mutex_unlock(su_mutex);
1031 }
1032
1033 static struct configfs_item_operations uvcg_streaming_header_item_ops = {
1034 .release = uvcg_config_item_release,
1035 .allow_link = uvcg_streaming_header_allow_link,
1036 .drop_link = uvcg_streaming_header_drop_link,
1037 };
1038
1039 #define UVCG_STREAMING_HEADER_ATTR(cname, aname, bits) \
1040 static ssize_t uvcg_streaming_header_##cname##_show( \
1041 struct config_item *item, char *page) \
1042 { \
1043 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
1044 struct f_uvc_opts *opts; \
1045 struct config_item *opts_item; \
1046 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
1047 int result; \
1048 \
1049 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1050 \
1051 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
1052 opts = to_f_uvc_opts(opts_item); \
1053 \
1054 mutex_lock(&opts->lock); \
1055 result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\
1056 mutex_unlock(&opts->lock); \
1057 \
1058 mutex_unlock(su_mutex); \
1059 return result; \
1060 } \
1061 \
1062 UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
1063
1064 UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, 8);
1065 UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, 8);
1066 UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, 8);
1067 UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, 8);
1068 UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, 8);
1069
1070 #undef UVCG_STREAMING_HEADER_ATTR
1071
1072 static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
1073 &uvcg_streaming_header_attr_bm_info,
1074 &uvcg_streaming_header_attr_b_terminal_link,
1075 &uvcg_streaming_header_attr_b_still_capture_method,
1076 &uvcg_streaming_header_attr_b_trigger_support,
1077 &uvcg_streaming_header_attr_b_trigger_usage,
1078 NULL,
1079 };
1080
1081 static const struct config_item_type uvcg_streaming_header_type = {
1082 .ct_item_ops = &uvcg_streaming_header_item_ops,
1083 .ct_attrs = uvcg_streaming_header_attrs,
1084 .ct_owner = THIS_MODULE,
1085 };
1086
1087 static struct config_item
uvcg_streaming_header_make(struct config_group * group,const char * name)1088 *uvcg_streaming_header_make(struct config_group *group, const char *name)
1089 {
1090 struct uvcg_streaming_header *h;
1091
1092 h = kzalloc(sizeof(*h), GFP_KERNEL);
1093 if (!h)
1094 return ERR_PTR(-ENOMEM);
1095
1096 INIT_LIST_HEAD(&h->formats);
1097 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1098 h->desc.bDescriptorSubType = UVC_VS_INPUT_HEADER;
1099 h->desc.bTerminalLink = 3;
1100 h->desc.bControlSize = UVCG_STREAMING_CONTROL_SIZE;
1101
1102 config_item_init_type_name(&h->item, name, &uvcg_streaming_header_type);
1103
1104 return &h->item;
1105 }
1106
1107 static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
1108 .make_item = uvcg_streaming_header_make,
1109 };
1110
1111 static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = {
1112 .type = {
1113 .ct_item_ops = &uvcg_config_item_ops,
1114 .ct_group_ops = &uvcg_streaming_header_grp_ops,
1115 .ct_owner = THIS_MODULE,
1116 },
1117 .name = "header",
1118 };
1119
1120 /* -----------------------------------------------------------------------------
1121 * streaming/<mode>/<format>/<NAME>
1122 */
1123
1124 struct uvcg_frame {
1125 struct config_item item;
1126 enum uvcg_format_type fmt_type;
1127 struct {
1128 u8 b_length;
1129 u8 b_descriptor_type;
1130 u8 b_descriptor_subtype;
1131 u8 b_frame_index;
1132 u8 bm_capabilities;
1133 u16 w_width;
1134 u16 w_height;
1135 u32 dw_min_bit_rate;
1136 u32 dw_max_bit_rate;
1137 u32 dw_max_video_frame_buffer_size;
1138 u32 dw_default_frame_interval;
1139 u8 b_frame_interval_type;
1140 } __attribute__((packed)) frame;
1141 u32 *dw_frame_interval;
1142 };
1143
to_uvcg_frame(struct config_item * item)1144 static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
1145 {
1146 return container_of(item, struct uvcg_frame, item);
1147 }
1148
1149 #define UVCG_FRAME_ATTR(cname, aname, bits) \
1150 static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
1151 { \
1152 struct uvcg_frame *f = to_uvcg_frame(item); \
1153 struct f_uvc_opts *opts; \
1154 struct config_item *opts_item; \
1155 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1156 int result; \
1157 \
1158 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1159 \
1160 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1161 opts = to_f_uvc_opts(opts_item); \
1162 \
1163 mutex_lock(&opts->lock); \
1164 result = sprintf(page, "%u\n", f->frame.cname); \
1165 mutex_unlock(&opts->lock); \
1166 \
1167 mutex_unlock(su_mutex); \
1168 return result; \
1169 } \
1170 \
1171 static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
1172 const char *page, size_t len)\
1173 { \
1174 struct uvcg_frame *f = to_uvcg_frame(item); \
1175 struct f_uvc_opts *opts; \
1176 struct config_item *opts_item; \
1177 struct uvcg_format *fmt; \
1178 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1179 typeof(f->frame.cname) num; \
1180 int ret; \
1181 \
1182 ret = kstrtou##bits(page, 0, &num); \
1183 if (ret) \
1184 return ret; \
1185 \
1186 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1187 \
1188 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1189 opts = to_f_uvc_opts(opts_item); \
1190 fmt = to_uvcg_format(f->item.ci_parent); \
1191 \
1192 mutex_lock(&opts->lock); \
1193 if (fmt->linked || opts->refcnt) { \
1194 ret = -EBUSY; \
1195 goto end; \
1196 } \
1197 \
1198 f->frame.cname = num; \
1199 ret = len; \
1200 end: \
1201 mutex_unlock(&opts->lock); \
1202 mutex_unlock(su_mutex); \
1203 return ret; \
1204 } \
1205 \
1206 UVC_ATTR(uvcg_frame_, cname, aname);
1207
uvcg_frame_b_frame_index_show(struct config_item * item,char * page)1208 static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
1209 char *page)
1210 {
1211 struct uvcg_frame *f = to_uvcg_frame(item);
1212 struct uvcg_format *fmt;
1213 struct f_uvc_opts *opts;
1214 struct config_item *opts_item;
1215 struct config_item *fmt_item;
1216 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;
1217 int result;
1218
1219 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1220
1221 fmt_item = f->item.ci_parent;
1222 fmt = to_uvcg_format(fmt_item);
1223
1224 if (!fmt->linked) {
1225 result = -EBUSY;
1226 goto out;
1227 }
1228
1229 opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
1230 opts = to_f_uvc_opts(opts_item);
1231
1232 mutex_lock(&opts->lock);
1233 result = sprintf(page, "%u\n", f->frame.b_frame_index);
1234 mutex_unlock(&opts->lock);
1235
1236 out:
1237 mutex_unlock(su_mutex);
1238 return result;
1239 }
1240
1241 UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
1242
1243 UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8);
1244 UVCG_FRAME_ATTR(w_width, wWidth, 16);
1245 UVCG_FRAME_ATTR(w_height, wHeight, 16);
1246 UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
1247 UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
1248 UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
1249 UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
1250
1251 #undef UVCG_FRAME_ATTR
1252
uvcg_frame_dw_frame_interval_show(struct config_item * item,char * page)1253 static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
1254 char *page)
1255 {
1256 struct uvcg_frame *frm = to_uvcg_frame(item);
1257 struct f_uvc_opts *opts;
1258 struct config_item *opts_item;
1259 struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
1260 int result, i;
1261 char *pg = page;
1262
1263 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1264
1265 opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
1266 opts = to_f_uvc_opts(opts_item);
1267
1268 mutex_lock(&opts->lock);
1269 for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
1270 result += sprintf(pg, "%u\n", frm->dw_frame_interval[i]);
1271 pg = page + result;
1272 }
1273 mutex_unlock(&opts->lock);
1274
1275 mutex_unlock(su_mutex);
1276 return result;
1277 }
1278
__uvcg_count_frm_intrv(char * buf,void * priv)1279 static inline int __uvcg_count_frm_intrv(char *buf, void *priv)
1280 {
1281 ++*((int *)priv);
1282 return 0;
1283 }
1284
__uvcg_fill_frm_intrv(char * buf,void * priv)1285 static inline int __uvcg_fill_frm_intrv(char *buf, void *priv)
1286 {
1287 u32 num, **interv;
1288 int ret;
1289
1290 ret = kstrtou32(buf, 0, &num);
1291 if (ret)
1292 return ret;
1293
1294 interv = priv;
1295 **interv = num;
1296 ++*interv;
1297
1298 return 0;
1299 }
1300
__uvcg_iter_frm_intrv(const char * page,size_t len,int (* fun)(char *,void *),void * priv)1301 static int __uvcg_iter_frm_intrv(const char *page, size_t len,
1302 int (*fun)(char *, void *), void *priv)
1303 {
1304 /* sign, base 2 representation, newline, terminator */
1305 char buf[1 + sizeof(u32) * 8 + 1 + 1];
1306 const char *pg = page;
1307 int i, ret;
1308
1309 if (!fun)
1310 return -EINVAL;
1311
1312 while (pg - page < len) {
1313 i = 0;
1314 while (i < sizeof(buf) && (pg - page < len) &&
1315 *pg != '\0' && *pg != '\n')
1316 buf[i++] = *pg++;
1317 if (i == sizeof(buf))
1318 return -EINVAL;
1319 while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
1320 ++pg;
1321 buf[i] = '\0';
1322 ret = fun(buf, priv);
1323 if (ret)
1324 return ret;
1325 }
1326
1327 return 0;
1328 }
1329
uvcg_frame_dw_frame_interval_store(struct config_item * item,const char * page,size_t len)1330 static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
1331 const char *page, size_t len)
1332 {
1333 struct uvcg_frame *ch = to_uvcg_frame(item);
1334 struct f_uvc_opts *opts;
1335 struct config_item *opts_item;
1336 struct uvcg_format *fmt;
1337 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
1338 int ret = 0, n = 0;
1339 u32 *frm_intrv, *tmp;
1340
1341 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1342
1343 opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
1344 opts = to_f_uvc_opts(opts_item);
1345 fmt = to_uvcg_format(ch->item.ci_parent);
1346
1347 mutex_lock(&opts->lock);
1348 if (fmt->linked || opts->refcnt) {
1349 ret = -EBUSY;
1350 goto end;
1351 }
1352
1353 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n);
1354 if (ret)
1355 goto end;
1356
1357 tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL);
1358 if (!frm_intrv) {
1359 ret = -ENOMEM;
1360 goto end;
1361 }
1362
1363 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp);
1364 if (ret) {
1365 kfree(frm_intrv);
1366 goto end;
1367 }
1368
1369 kfree(ch->dw_frame_interval);
1370 ch->dw_frame_interval = frm_intrv;
1371 ch->frame.b_frame_interval_type = n;
1372 sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
1373 uvcg_config_compare_u32, NULL);
1374 ret = len;
1375
1376 end:
1377 mutex_unlock(&opts->lock);
1378 mutex_unlock(su_mutex);
1379 return ret;
1380 }
1381
1382 UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
1383
1384 static struct configfs_attribute *uvcg_frame_attrs[] = {
1385 &uvcg_frame_attr_b_frame_index,
1386 &uvcg_frame_attr_bm_capabilities,
1387 &uvcg_frame_attr_w_width,
1388 &uvcg_frame_attr_w_height,
1389 &uvcg_frame_attr_dw_min_bit_rate,
1390 &uvcg_frame_attr_dw_max_bit_rate,
1391 &uvcg_frame_attr_dw_max_video_frame_buffer_size,
1392 &uvcg_frame_attr_dw_default_frame_interval,
1393 &uvcg_frame_attr_dw_frame_interval,
1394 NULL,
1395 };
1396
1397 static const struct config_item_type uvcg_frame_type = {
1398 .ct_item_ops = &uvcg_config_item_ops,
1399 .ct_attrs = uvcg_frame_attrs,
1400 .ct_owner = THIS_MODULE,
1401 };
1402
uvcg_frame_make(struct config_group * group,const char * name)1403 static struct config_item *uvcg_frame_make(struct config_group *group,
1404 const char *name)
1405 {
1406 struct uvcg_frame *h;
1407 struct uvcg_format *fmt;
1408 struct f_uvc_opts *opts;
1409 struct config_item *opts_item;
1410
1411 h = kzalloc(sizeof(*h), GFP_KERNEL);
1412 if (!h)
1413 return ERR_PTR(-ENOMEM);
1414
1415 h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
1416 h->frame.b_frame_index = 1;
1417 h->frame.w_width = 640;
1418 h->frame.w_height = 360;
1419 h->frame.dw_min_bit_rate = 18432000;
1420 h->frame.dw_max_bit_rate = 55296000;
1421 h->frame.dw_max_video_frame_buffer_size = 460800;
1422 h->frame.dw_default_frame_interval = 666666;
1423
1424 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1425 opts = to_f_uvc_opts(opts_item);
1426
1427 mutex_lock(&opts->lock);
1428 fmt = to_uvcg_format(&group->cg_item);
1429 if (fmt->type == UVCG_UNCOMPRESSED) {
1430 h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED;
1431 h->fmt_type = UVCG_UNCOMPRESSED;
1432 } else if (fmt->type == UVCG_MJPEG) {
1433 h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
1434 h->fmt_type = UVCG_MJPEG;
1435 } else {
1436 mutex_unlock(&opts->lock);
1437 kfree(h);
1438 return ERR_PTR(-EINVAL);
1439 }
1440 ++fmt->num_frames;
1441 mutex_unlock(&opts->lock);
1442
1443 config_item_init_type_name(&h->item, name, &uvcg_frame_type);
1444
1445 return &h->item;
1446 }
1447
uvcg_frame_drop(struct config_group * group,struct config_item * item)1448 static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
1449 {
1450 struct uvcg_format *fmt;
1451 struct f_uvc_opts *opts;
1452 struct config_item *opts_item;
1453
1454 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
1455 opts = to_f_uvc_opts(opts_item);
1456
1457 mutex_lock(&opts->lock);
1458 fmt = to_uvcg_format(&group->cg_item);
1459 --fmt->num_frames;
1460 mutex_unlock(&opts->lock);
1461
1462 config_item_put(item);
1463 }
1464
uvcg_format_set_indices(struct config_group * fmt)1465 static void uvcg_format_set_indices(struct config_group *fmt)
1466 {
1467 struct config_item *ci;
1468 unsigned int i = 1;
1469
1470 list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
1471 struct uvcg_frame *frm;
1472
1473 if (ci->ci_type != &uvcg_frame_type)
1474 continue;
1475
1476 frm = to_uvcg_frame(ci);
1477 frm->frame.b_frame_index = i++;
1478 }
1479 }
1480
1481 /* -----------------------------------------------------------------------------
1482 * streaming/uncompressed/<NAME>
1483 */
1484
1485 struct uvcg_uncompressed {
1486 struct uvcg_format fmt;
1487 struct uvc_format_uncompressed desc;
1488 };
1489
to_uvcg_uncompressed(struct config_item * item)1490 static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item)
1491 {
1492 return container_of(
1493 container_of(to_config_group(item), struct uvcg_format, group),
1494 struct uvcg_uncompressed, fmt);
1495 }
1496
1497 static struct configfs_group_operations uvcg_uncompressed_group_ops = {
1498 .make_item = uvcg_frame_make,
1499 .drop_item = uvcg_frame_drop,
1500 };
1501
uvcg_uncompressed_guid_format_show(struct config_item * item,char * page)1502 static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
1503 char *page)
1504 {
1505 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1506 struct f_uvc_opts *opts;
1507 struct config_item *opts_item;
1508 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1509
1510 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1511
1512 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1513 opts = to_f_uvc_opts(opts_item);
1514
1515 mutex_lock(&opts->lock);
1516 memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
1517 mutex_unlock(&opts->lock);
1518
1519 mutex_unlock(su_mutex);
1520
1521 return sizeof(ch->desc.guidFormat);
1522 }
1523
uvcg_uncompressed_guid_format_store(struct config_item * item,const char * page,size_t len)1524 static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
1525 const char *page, size_t len)
1526 {
1527 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
1528 struct f_uvc_opts *opts;
1529 struct config_item *opts_item;
1530 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
1531 int ret;
1532
1533 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1534
1535 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
1536 opts = to_f_uvc_opts(opts_item);
1537
1538 mutex_lock(&opts->lock);
1539 if (ch->fmt.linked || opts->refcnt) {
1540 ret = -EBUSY;
1541 goto end;
1542 }
1543
1544 memcpy(ch->desc.guidFormat, page,
1545 min(sizeof(ch->desc.guidFormat), len));
1546 ret = sizeof(ch->desc.guidFormat);
1547
1548 end:
1549 mutex_unlock(&opts->lock);
1550 mutex_unlock(su_mutex);
1551 return ret;
1552 }
1553
1554 UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
1555
1556 #define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, bits) \
1557 static ssize_t uvcg_uncompressed_##cname##_show( \
1558 struct config_item *item, char *page) \
1559 { \
1560 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1561 struct f_uvc_opts *opts; \
1562 struct config_item *opts_item; \
1563 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1564 int result; \
1565 \
1566 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1567 \
1568 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1569 opts = to_f_uvc_opts(opts_item); \
1570 \
1571 mutex_lock(&opts->lock); \
1572 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1573 mutex_unlock(&opts->lock); \
1574 \
1575 mutex_unlock(su_mutex); \
1576 return result; \
1577 } \
1578 \
1579 UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
1580
1581 #define UVCG_UNCOMPRESSED_ATTR(cname, aname, bits) \
1582 static ssize_t uvcg_uncompressed_##cname##_show( \
1583 struct config_item *item, char *page) \
1584 { \
1585 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1586 struct f_uvc_opts *opts; \
1587 struct config_item *opts_item; \
1588 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1589 int result; \
1590 \
1591 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1592 \
1593 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1594 opts = to_f_uvc_opts(opts_item); \
1595 \
1596 mutex_lock(&opts->lock); \
1597 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1598 mutex_unlock(&opts->lock); \
1599 \
1600 mutex_unlock(su_mutex); \
1601 return result; \
1602 } \
1603 \
1604 static ssize_t \
1605 uvcg_uncompressed_##cname##_store(struct config_item *item, \
1606 const char *page, size_t len) \
1607 { \
1608 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
1609 struct f_uvc_opts *opts; \
1610 struct config_item *opts_item; \
1611 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1612 int ret; \
1613 u8 num; \
1614 \
1615 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1616 \
1617 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1618 opts = to_f_uvc_opts(opts_item); \
1619 \
1620 mutex_lock(&opts->lock); \
1621 if (u->fmt.linked || opts->refcnt) { \
1622 ret = -EBUSY; \
1623 goto end; \
1624 } \
1625 \
1626 ret = kstrtou8(page, 0, &num); \
1627 if (ret) \
1628 goto end; \
1629 \
1630 u->desc.aname = num; \
1631 ret = len; \
1632 end: \
1633 mutex_unlock(&opts->lock); \
1634 mutex_unlock(su_mutex); \
1635 return ret; \
1636 } \
1637 \
1638 UVC_ATTR(uvcg_uncompressed_, cname, aname);
1639
1640 UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, 8);
1641 UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8);
1642 UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
1643 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
1644 UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
1645 UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
1646
1647 #undef UVCG_UNCOMPRESSED_ATTR
1648 #undef UVCG_UNCOMPRESSED_ATTR_RO
1649
1650 static inline ssize_t
uvcg_uncompressed_bma_controls_show(struct config_item * item,char * page)1651 uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
1652 {
1653 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1654 return uvcg_format_bma_controls_show(&unc->fmt, page);
1655 }
1656
1657 static inline ssize_t
uvcg_uncompressed_bma_controls_store(struct config_item * item,const char * page,size_t len)1658 uvcg_uncompressed_bma_controls_store(struct config_item *item,
1659 const char *page, size_t len)
1660 {
1661 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
1662 return uvcg_format_bma_controls_store(&unc->fmt, page, len);
1663 }
1664
1665 UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
1666
1667 static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
1668 &uvcg_uncompressed_attr_b_format_index,
1669 &uvcg_uncompressed_attr_guid_format,
1670 &uvcg_uncompressed_attr_b_bits_per_pixel,
1671 &uvcg_uncompressed_attr_b_default_frame_index,
1672 &uvcg_uncompressed_attr_b_aspect_ratio_x,
1673 &uvcg_uncompressed_attr_b_aspect_ratio_y,
1674 &uvcg_uncompressed_attr_bm_interface_flags,
1675 &uvcg_uncompressed_attr_bma_controls,
1676 NULL,
1677 };
1678
1679 static const struct config_item_type uvcg_uncompressed_type = {
1680 .ct_item_ops = &uvcg_config_item_ops,
1681 .ct_group_ops = &uvcg_uncompressed_group_ops,
1682 .ct_attrs = uvcg_uncompressed_attrs,
1683 .ct_owner = THIS_MODULE,
1684 };
1685
uvcg_uncompressed_make(struct config_group * group,const char * name)1686 static struct config_group *uvcg_uncompressed_make(struct config_group *group,
1687 const char *name)
1688 {
1689 static char guid[] = {
1690 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
1691 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
1692 };
1693 struct uvcg_uncompressed *h;
1694
1695 h = kzalloc(sizeof(*h), GFP_KERNEL);
1696 if (!h)
1697 return ERR_PTR(-ENOMEM);
1698
1699 h->desc.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE;
1700 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1701 h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED;
1702 memcpy(h->desc.guidFormat, guid, sizeof(guid));
1703 h->desc.bBitsPerPixel = 16;
1704 h->desc.bDefaultFrameIndex = 1;
1705 h->desc.bAspectRatioX = 0;
1706 h->desc.bAspectRatioY = 0;
1707 h->desc.bmInterfaceFlags = 0;
1708 h->desc.bCopyProtect = 0;
1709
1710 h->fmt.type = UVCG_UNCOMPRESSED;
1711 config_group_init_type_name(&h->fmt.group, name,
1712 &uvcg_uncompressed_type);
1713
1714 return &h->fmt.group;
1715 }
1716
1717 static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
1718 .make_group = uvcg_uncompressed_make,
1719 };
1720
1721 static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = {
1722 .type = {
1723 .ct_item_ops = &uvcg_config_item_ops,
1724 .ct_group_ops = &uvcg_uncompressed_grp_ops,
1725 .ct_owner = THIS_MODULE,
1726 },
1727 .name = "uncompressed",
1728 };
1729
1730 /* -----------------------------------------------------------------------------
1731 * streaming/mjpeg/<NAME>
1732 */
1733
1734 struct uvcg_mjpeg {
1735 struct uvcg_format fmt;
1736 struct uvc_format_mjpeg desc;
1737 };
1738
to_uvcg_mjpeg(struct config_item * item)1739 static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
1740 {
1741 return container_of(
1742 container_of(to_config_group(item), struct uvcg_format, group),
1743 struct uvcg_mjpeg, fmt);
1744 }
1745
1746 static struct configfs_group_operations uvcg_mjpeg_group_ops = {
1747 .make_item = uvcg_frame_make,
1748 .drop_item = uvcg_frame_drop,
1749 };
1750
1751 #define UVCG_MJPEG_ATTR_RO(cname, aname, bits) \
1752 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1753 { \
1754 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1755 struct f_uvc_opts *opts; \
1756 struct config_item *opts_item; \
1757 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1758 int result; \
1759 \
1760 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1761 \
1762 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1763 opts = to_f_uvc_opts(opts_item); \
1764 \
1765 mutex_lock(&opts->lock); \
1766 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1767 mutex_unlock(&opts->lock); \
1768 \
1769 mutex_unlock(su_mutex); \
1770 return result; \
1771 } \
1772 \
1773 UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
1774
1775 #define UVCG_MJPEG_ATTR(cname, aname, bits) \
1776 static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
1777 { \
1778 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1779 struct f_uvc_opts *opts; \
1780 struct config_item *opts_item; \
1781 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1782 int result; \
1783 \
1784 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1785 \
1786 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1787 opts = to_f_uvc_opts(opts_item); \
1788 \
1789 mutex_lock(&opts->lock); \
1790 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
1791 mutex_unlock(&opts->lock); \
1792 \
1793 mutex_unlock(su_mutex); \
1794 return result; \
1795 } \
1796 \
1797 static ssize_t \
1798 uvcg_mjpeg_##cname##_store(struct config_item *item, \
1799 const char *page, size_t len) \
1800 { \
1801 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
1802 struct f_uvc_opts *opts; \
1803 struct config_item *opts_item; \
1804 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
1805 int ret; \
1806 u8 num; \
1807 \
1808 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1809 \
1810 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
1811 opts = to_f_uvc_opts(opts_item); \
1812 \
1813 mutex_lock(&opts->lock); \
1814 if (u->fmt.linked || opts->refcnt) { \
1815 ret = -EBUSY; \
1816 goto end; \
1817 } \
1818 \
1819 ret = kstrtou8(page, 0, &num); \
1820 if (ret) \
1821 goto end; \
1822 \
1823 u->desc.aname = num; \
1824 ret = len; \
1825 end: \
1826 mutex_unlock(&opts->lock); \
1827 mutex_unlock(su_mutex); \
1828 return ret; \
1829 } \
1830 \
1831 UVC_ATTR(uvcg_mjpeg_, cname, aname)
1832
1833 UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, 8);
1834 UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
1835 UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8);
1836 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
1837 UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
1838 UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
1839
1840 #undef UVCG_MJPEG_ATTR
1841 #undef UVCG_MJPEG_ATTR_RO
1842
1843 static inline ssize_t
uvcg_mjpeg_bma_controls_show(struct config_item * item,char * page)1844 uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
1845 {
1846 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1847 return uvcg_format_bma_controls_show(&u->fmt, page);
1848 }
1849
1850 static inline ssize_t
uvcg_mjpeg_bma_controls_store(struct config_item * item,const char * page,size_t len)1851 uvcg_mjpeg_bma_controls_store(struct config_item *item,
1852 const char *page, size_t len)
1853 {
1854 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
1855 return uvcg_format_bma_controls_store(&u->fmt, page, len);
1856 }
1857
1858 UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
1859
1860 static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
1861 &uvcg_mjpeg_attr_b_format_index,
1862 &uvcg_mjpeg_attr_b_default_frame_index,
1863 &uvcg_mjpeg_attr_bm_flags,
1864 &uvcg_mjpeg_attr_b_aspect_ratio_x,
1865 &uvcg_mjpeg_attr_b_aspect_ratio_y,
1866 &uvcg_mjpeg_attr_bm_interface_flags,
1867 &uvcg_mjpeg_attr_bma_controls,
1868 NULL,
1869 };
1870
1871 static const struct config_item_type uvcg_mjpeg_type = {
1872 .ct_item_ops = &uvcg_config_item_ops,
1873 .ct_group_ops = &uvcg_mjpeg_group_ops,
1874 .ct_attrs = uvcg_mjpeg_attrs,
1875 .ct_owner = THIS_MODULE,
1876 };
1877
uvcg_mjpeg_make(struct config_group * group,const char * name)1878 static struct config_group *uvcg_mjpeg_make(struct config_group *group,
1879 const char *name)
1880 {
1881 struct uvcg_mjpeg *h;
1882
1883 h = kzalloc(sizeof(*h), GFP_KERNEL);
1884 if (!h)
1885 return ERR_PTR(-ENOMEM);
1886
1887 h->desc.bLength = UVC_DT_FORMAT_MJPEG_SIZE;
1888 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1889 h->desc.bDescriptorSubType = UVC_VS_FORMAT_MJPEG;
1890 h->desc.bDefaultFrameIndex = 1;
1891 h->desc.bAspectRatioX = 0;
1892 h->desc.bAspectRatioY = 0;
1893 h->desc.bmInterfaceFlags = 0;
1894 h->desc.bCopyProtect = 0;
1895
1896 h->fmt.type = UVCG_MJPEG;
1897 config_group_init_type_name(&h->fmt.group, name,
1898 &uvcg_mjpeg_type);
1899
1900 return &h->fmt.group;
1901 }
1902
1903 static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
1904 .make_group = uvcg_mjpeg_make,
1905 };
1906
1907 static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
1908 .type = {
1909 .ct_item_ops = &uvcg_config_item_ops,
1910 .ct_group_ops = &uvcg_mjpeg_grp_ops,
1911 .ct_owner = THIS_MODULE,
1912 },
1913 .name = "mjpeg",
1914 };
1915
1916 /* -----------------------------------------------------------------------------
1917 * streaming/color_matching/default
1918 */
1919
1920 #define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, bits) \
1921 static ssize_t uvcg_default_color_matching_##cname##_show( \
1922 struct config_item *item, char *page) \
1923 { \
1924 struct config_group *group = to_config_group(item); \
1925 struct f_uvc_opts *opts; \
1926 struct config_item *opts_item; \
1927 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
1928 struct uvc_color_matching_descriptor *cd; \
1929 int result; \
1930 \
1931 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1932 \
1933 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
1934 opts = to_f_uvc_opts(opts_item); \
1935 cd = &opts->uvc_color_matching; \
1936 \
1937 mutex_lock(&opts->lock); \
1938 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
1939 mutex_unlock(&opts->lock); \
1940 \
1941 mutex_unlock(su_mutex); \
1942 return result; \
1943 } \
1944 \
1945 UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
1946
1947 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 8);
1948 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics,
1949 bTransferCharacteristics, 8);
1950 UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 8);
1951
1952 #undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
1953
1954 static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
1955 &uvcg_default_color_matching_attr_b_color_primaries,
1956 &uvcg_default_color_matching_attr_b_transfer_characteristics,
1957 &uvcg_default_color_matching_attr_b_matrix_coefficients,
1958 NULL,
1959 };
1960
1961 static const struct uvcg_config_group_type uvcg_default_color_matching_type = {
1962 .type = {
1963 .ct_item_ops = &uvcg_config_item_ops,
1964 .ct_attrs = uvcg_default_color_matching_attrs,
1965 .ct_owner = THIS_MODULE,
1966 },
1967 .name = "default",
1968 };
1969
1970 /* -----------------------------------------------------------------------------
1971 * streaming/color_matching
1972 */
1973
1974 static const struct uvcg_config_group_type uvcg_color_matching_grp_type = {
1975 .type = {
1976 .ct_item_ops = &uvcg_config_item_ops,
1977 .ct_owner = THIS_MODULE,
1978 },
1979 .name = "color_matching",
1980 .children = (const struct uvcg_config_group_type*[]) {
1981 &uvcg_default_color_matching_type,
1982 NULL,
1983 },
1984 };
1985
1986 /* -----------------------------------------------------------------------------
1987 * streaming/class/{fs|hs|ss}
1988 */
1989
1990 struct uvcg_streaming_class_group {
1991 struct config_group group;
1992 const char *name;
1993 };
1994
1995 static inline struct uvc_descriptor_header
__uvcg_get_stream_class_arr(struct config_item * i,struct f_uvc_opts * o)1996 ***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
1997 {
1998 struct uvcg_streaming_class_group *group =
1999 container_of(i, struct uvcg_streaming_class_group,
2000 group.cg_item);
2001
2002 if (!strcmp(group->name, "fs"))
2003 return &o->uvc_fs_streaming_cls;
2004
2005 if (!strcmp(group->name, "hs"))
2006 return &o->uvc_hs_streaming_cls;
2007
2008 if (!strcmp(group->name, "ss"))
2009 return &o->uvc_ss_streaming_cls;
2010
2011 return NULL;
2012 }
2013
2014 enum uvcg_strm_type {
2015 UVCG_HEADER = 0,
2016 UVCG_FORMAT,
2017 UVCG_FRAME
2018 };
2019
2020 /*
2021 * Iterate over a hierarchy of streaming descriptors' config items.
2022 * The items are created by the user with configfs.
2023 *
2024 * It "processes" the header pointed to by @priv1, then for each format
2025 * that follows the header "processes" the format itself and then for
2026 * each frame inside a format "processes" the frame.
2027 *
2028 * As a "processing" function the @fun is used.
2029 *
2030 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
2031 * the amount of memory needed for an array of streaming descriptors
2032 * and second, to actually fill the array.
2033 *
2034 * @h: streaming header pointer
2035 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
2036 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
2037 * @fun: callback function for processing each level of the hierarchy
2038 */
__uvcg_iter_strm_cls(struct uvcg_streaming_header * h,void * priv2,void * priv3,int (* fun)(void *,void *,void *,int,enum uvcg_strm_type type))2039 static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
2040 void *priv2, void *priv3,
2041 int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type))
2042 {
2043 struct uvcg_format_ptr *f;
2044 struct config_group *grp;
2045 struct config_item *item;
2046 struct uvcg_frame *frm;
2047 int ret, i, j;
2048
2049 if (!fun)
2050 return -EINVAL;
2051
2052 i = j = 0;
2053 ret = fun(h, priv2, priv3, 0, UVCG_HEADER);
2054 if (ret)
2055 return ret;
2056 list_for_each_entry(f, &h->formats, entry) {
2057 ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT);
2058 if (ret)
2059 return ret;
2060 grp = &f->fmt->group;
2061 list_for_each_entry(item, &grp->cg_children, ci_entry) {
2062 frm = to_uvcg_frame(item);
2063 ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
2064 if (ret)
2065 return ret;
2066 }
2067 }
2068
2069 return ret;
2070 }
2071
2072 /*
2073 * Count how many bytes are needed for an array of streaming descriptors.
2074 *
2075 * @priv1: pointer to a header, format or frame
2076 * @priv2: inout parameter, accumulated size of the array
2077 * @priv3: inout parameter, accumulated number of the array elements
2078 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
2079 */
__uvcg_cnt_strm(void * priv1,void * priv2,void * priv3,int n,enum uvcg_strm_type type)2080 static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
2081 enum uvcg_strm_type type)
2082 {
2083 size_t *size = priv2;
2084 size_t *count = priv3;
2085
2086 switch (type) {
2087 case UVCG_HEADER: {
2088 struct uvcg_streaming_header *h = priv1;
2089
2090 *size += sizeof(h->desc);
2091 /* bmaControls */
2092 *size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE;
2093 }
2094 break;
2095 case UVCG_FORMAT: {
2096 struct uvcg_format *fmt = priv1;
2097
2098 if (fmt->type == UVCG_UNCOMPRESSED) {
2099 struct uvcg_uncompressed *u =
2100 container_of(fmt, struct uvcg_uncompressed,
2101 fmt);
2102
2103 *size += sizeof(u->desc);
2104 } else if (fmt->type == UVCG_MJPEG) {
2105 struct uvcg_mjpeg *m =
2106 container_of(fmt, struct uvcg_mjpeg, fmt);
2107
2108 *size += sizeof(m->desc);
2109 } else {
2110 return -EINVAL;
2111 }
2112 }
2113 break;
2114 case UVCG_FRAME: {
2115 struct uvcg_frame *frm = priv1;
2116 int sz = sizeof(frm->dw_frame_interval);
2117
2118 *size += sizeof(frm->frame);
2119 *size += frm->frame.b_frame_interval_type * sz;
2120 }
2121 break;
2122 }
2123
2124 ++*count;
2125
2126 return 0;
2127 }
2128
2129 /*
2130 * Fill an array of streaming descriptors.
2131 *
2132 * @priv1: pointer to a header, format or frame
2133 * @priv2: inout parameter, pointer into a block of memory
2134 * @priv3: inout parameter, pointer to a 2-dimensional array
2135 */
__uvcg_fill_strm(void * priv1,void * priv2,void * priv3,int n,enum uvcg_strm_type type)2136 static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
2137 enum uvcg_strm_type type)
2138 {
2139 void **dest = priv2;
2140 struct uvc_descriptor_header ***array = priv3;
2141 size_t sz;
2142
2143 **array = *dest;
2144 ++*array;
2145
2146 switch (type) {
2147 case UVCG_HEADER: {
2148 struct uvc_input_header_descriptor *ihdr = *dest;
2149 struct uvcg_streaming_header *h = priv1;
2150 struct uvcg_format_ptr *f;
2151
2152 memcpy(*dest, &h->desc, sizeof(h->desc));
2153 *dest += sizeof(h->desc);
2154 sz = UVCG_STREAMING_CONTROL_SIZE;
2155 list_for_each_entry(f, &h->formats, entry) {
2156 memcpy(*dest, f->fmt->bmaControls, sz);
2157 *dest += sz;
2158 }
2159 ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz;
2160 ihdr->bNumFormats = h->num_fmt;
2161 }
2162 break;
2163 case UVCG_FORMAT: {
2164 struct uvcg_format *fmt = priv1;
2165
2166 if (fmt->type == UVCG_UNCOMPRESSED) {
2167 struct uvcg_uncompressed *u =
2168 container_of(fmt, struct uvcg_uncompressed,
2169 fmt);
2170
2171 u->desc.bFormatIndex = n + 1;
2172 u->desc.bNumFrameDescriptors = fmt->num_frames;
2173 memcpy(*dest, &u->desc, sizeof(u->desc));
2174 *dest += sizeof(u->desc);
2175 } else if (fmt->type == UVCG_MJPEG) {
2176 struct uvcg_mjpeg *m =
2177 container_of(fmt, struct uvcg_mjpeg, fmt);
2178
2179 m->desc.bFormatIndex = n + 1;
2180 m->desc.bNumFrameDescriptors = fmt->num_frames;
2181 memcpy(*dest, &m->desc, sizeof(m->desc));
2182 *dest += sizeof(m->desc);
2183 } else {
2184 return -EINVAL;
2185 }
2186 }
2187 break;
2188 case UVCG_FRAME: {
2189 struct uvcg_frame *frm = priv1;
2190 struct uvc_descriptor_header *h = *dest;
2191
2192 sz = sizeof(frm->frame);
2193 memcpy(*dest, &frm->frame, sz);
2194 *dest += sz;
2195 sz = frm->frame.b_frame_interval_type *
2196 sizeof(*frm->dw_frame_interval);
2197 memcpy(*dest, frm->dw_frame_interval, sz);
2198 *dest += sz;
2199 if (frm->fmt_type == UVCG_UNCOMPRESSED)
2200 h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
2201 frm->frame.b_frame_interval_type);
2202 else if (frm->fmt_type == UVCG_MJPEG)
2203 h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
2204 frm->frame.b_frame_interval_type);
2205 }
2206 break;
2207 }
2208
2209 return 0;
2210 }
2211
uvcg_streaming_class_allow_link(struct config_item * src,struct config_item * target)2212 static int uvcg_streaming_class_allow_link(struct config_item *src,
2213 struct config_item *target)
2214 {
2215 struct config_item *streaming, *header;
2216 struct f_uvc_opts *opts;
2217 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2218 struct uvc_descriptor_header ***class_array, **cl_arr;
2219 struct uvcg_streaming_header *target_hdr;
2220 void *data, *data_save;
2221 size_t size = 0, count = 0;
2222 int ret = -EINVAL;
2223
2224 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2225
2226 streaming = src->ci_parent->ci_parent;
2227 header = config_group_find_item(to_config_group(streaming), "header");
2228 if (!header || target->ci_parent != header)
2229 goto out;
2230
2231 opts = to_f_uvc_opts(streaming->ci_parent);
2232
2233 mutex_lock(&opts->lock);
2234
2235 class_array = __uvcg_get_stream_class_arr(src, opts);
2236 if (!class_array || *class_array || opts->refcnt) {
2237 ret = -EBUSY;
2238 goto unlock;
2239 }
2240
2241 target_hdr = to_uvcg_streaming_header(target);
2242 ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm);
2243 if (ret)
2244 goto unlock;
2245
2246 count += 2; /* color_matching, NULL */
2247 *class_array = kcalloc(count, sizeof(void *), GFP_KERNEL);
2248 if (!*class_array) {
2249 ret = -ENOMEM;
2250 goto unlock;
2251 }
2252
2253 data = data_save = kzalloc(size, GFP_KERNEL);
2254 if (!data) {
2255 kfree(*class_array);
2256 *class_array = NULL;
2257 ret = -ENOMEM;
2258 goto unlock;
2259 }
2260 cl_arr = *class_array;
2261 ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr,
2262 __uvcg_fill_strm);
2263 if (ret) {
2264 kfree(*class_array);
2265 *class_array = NULL;
2266 /*
2267 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
2268 * might have advanced the "data", so use a backup copy
2269 */
2270 kfree(data_save);
2271 goto unlock;
2272 }
2273 *cl_arr = (struct uvc_descriptor_header *)&opts->uvc_color_matching;
2274
2275 ++target_hdr->linked;
2276 ret = 0;
2277
2278 unlock:
2279 mutex_unlock(&opts->lock);
2280 out:
2281 config_item_put(header);
2282 mutex_unlock(su_mutex);
2283 return ret;
2284 }
2285
uvcg_streaming_class_drop_link(struct config_item * src,struct config_item * target)2286 static void uvcg_streaming_class_drop_link(struct config_item *src,
2287 struct config_item *target)
2288 {
2289 struct config_item *streaming, *header;
2290 struct f_uvc_opts *opts;
2291 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2292 struct uvc_descriptor_header ***class_array;
2293 struct uvcg_streaming_header *target_hdr;
2294
2295 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2296
2297 streaming = src->ci_parent->ci_parent;
2298 header = config_group_find_item(to_config_group(streaming), "header");
2299 if (!header || target->ci_parent != header)
2300 goto out;
2301
2302 opts = to_f_uvc_opts(streaming->ci_parent);
2303
2304 mutex_lock(&opts->lock);
2305
2306 class_array = __uvcg_get_stream_class_arr(src, opts);
2307 if (!class_array || !*class_array)
2308 goto unlock;
2309
2310 if (opts->refcnt)
2311 goto unlock;
2312
2313 target_hdr = to_uvcg_streaming_header(target);
2314 --target_hdr->linked;
2315 kfree(**class_array);
2316 kfree(*class_array);
2317 *class_array = NULL;
2318
2319 unlock:
2320 mutex_unlock(&opts->lock);
2321 out:
2322 config_item_put(header);
2323 mutex_unlock(su_mutex);
2324 }
2325
2326 static struct configfs_item_operations uvcg_streaming_class_item_ops = {
2327 .release = uvcg_config_item_release,
2328 .allow_link = uvcg_streaming_class_allow_link,
2329 .drop_link = uvcg_streaming_class_drop_link,
2330 };
2331
2332 static const struct config_item_type uvcg_streaming_class_type = {
2333 .ct_item_ops = &uvcg_streaming_class_item_ops,
2334 .ct_owner = THIS_MODULE,
2335 };
2336
2337 /* -----------------------------------------------------------------------------
2338 * streaming/class
2339 */
2340
uvcg_streaming_class_create_children(struct config_group * parent)2341 static int uvcg_streaming_class_create_children(struct config_group *parent)
2342 {
2343 static const char * const names[] = { "fs", "hs", "ss" };
2344 unsigned int i;
2345
2346 for (i = 0; i < ARRAY_SIZE(names); ++i) {
2347 struct uvcg_streaming_class_group *group;
2348
2349 group = kzalloc(sizeof(*group), GFP_KERNEL);
2350 if (!group)
2351 return -ENOMEM;
2352
2353 group->name = names[i];
2354
2355 config_group_init_type_name(&group->group, group->name,
2356 &uvcg_streaming_class_type);
2357 configfs_add_default_group(&group->group, parent);
2358 }
2359
2360 return 0;
2361 }
2362
2363 static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = {
2364 .type = {
2365 .ct_item_ops = &uvcg_config_item_ops,
2366 .ct_owner = THIS_MODULE,
2367 },
2368 .name = "class",
2369 .create_children = uvcg_streaming_class_create_children,
2370 };
2371
2372 /* -----------------------------------------------------------------------------
2373 * streaming
2374 */
2375
uvcg_default_streaming_b_interface_number_show(struct config_item * item,char * page)2376 static ssize_t uvcg_default_streaming_b_interface_number_show(
2377 struct config_item *item, char *page)
2378 {
2379 struct config_group *group = to_config_group(item);
2380 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
2381 struct config_item *opts_item;
2382 struct f_uvc_opts *opts;
2383 int result = 0;
2384
2385 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2386
2387 opts_item = item->ci_parent;
2388 opts = to_f_uvc_opts(opts_item);
2389
2390 mutex_lock(&opts->lock);
2391 result += sprintf(page, "%u\n", opts->streaming_interface);
2392 mutex_unlock(&opts->lock);
2393
2394 mutex_unlock(su_mutex);
2395
2396 return result;
2397 }
2398
2399 UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber);
2400
2401 static struct configfs_attribute *uvcg_default_streaming_attrs[] = {
2402 &uvcg_default_streaming_attr_b_interface_number,
2403 NULL,
2404 };
2405
2406 static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
2407 .type = {
2408 .ct_item_ops = &uvcg_config_item_ops,
2409 .ct_attrs = uvcg_default_streaming_attrs,
2410 .ct_owner = THIS_MODULE,
2411 },
2412 .name = "streaming",
2413 .children = (const struct uvcg_config_group_type*[]) {
2414 &uvcg_streaming_header_grp_type,
2415 &uvcg_uncompressed_grp_type,
2416 &uvcg_mjpeg_grp_type,
2417 &uvcg_color_matching_grp_type,
2418 &uvcg_streaming_class_grp_type,
2419 NULL,
2420 },
2421 };
2422
2423 /* -----------------------------------------------------------------------------
2424 * UVC function
2425 */
2426
uvc_func_item_release(struct config_item * item)2427 static void uvc_func_item_release(struct config_item *item)
2428 {
2429 struct f_uvc_opts *opts = to_f_uvc_opts(item);
2430
2431 uvcg_config_remove_children(to_config_group(item));
2432 usb_put_function_instance(&opts->func_inst);
2433 }
2434
2435 static struct configfs_item_operations uvc_func_item_ops = {
2436 .release = uvc_func_item_release,
2437 };
2438
2439 #define UVCG_OPTS_ATTR(cname, aname, limit) \
2440 static ssize_t f_uvc_opts_##cname##_show( \
2441 struct config_item *item, char *page) \
2442 { \
2443 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2444 int result; \
2445 \
2446 mutex_lock(&opts->lock); \
2447 result = sprintf(page, "%u\n", opts->cname); \
2448 mutex_unlock(&opts->lock); \
2449 \
2450 return result; \
2451 } \
2452 \
2453 static ssize_t \
2454 f_uvc_opts_##cname##_store(struct config_item *item, \
2455 const char *page, size_t len) \
2456 { \
2457 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
2458 unsigned int num; \
2459 int ret; \
2460 \
2461 mutex_lock(&opts->lock); \
2462 if (opts->refcnt) { \
2463 ret = -EBUSY; \
2464 goto end; \
2465 } \
2466 \
2467 ret = kstrtouint(page, 0, &num); \
2468 if (ret) \
2469 goto end; \
2470 \
2471 if (num > limit) { \
2472 ret = -EINVAL; \
2473 goto end; \
2474 } \
2475 opts->cname = num; \
2476 ret = len; \
2477 end: \
2478 mutex_unlock(&opts->lock); \
2479 return ret; \
2480 } \
2481 \
2482 UVC_ATTR(f_uvc_opts_, cname, cname)
2483
2484 UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16);
2485 UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072);
2486 UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15);
2487
2488 #undef UVCG_OPTS_ATTR
2489
2490 static struct configfs_attribute *uvc_attrs[] = {
2491 &f_uvc_opts_attr_streaming_interval,
2492 &f_uvc_opts_attr_streaming_maxpacket,
2493 &f_uvc_opts_attr_streaming_maxburst,
2494 NULL,
2495 };
2496
2497 static const struct uvcg_config_group_type uvc_func_type = {
2498 .type = {
2499 .ct_item_ops = &uvc_func_item_ops,
2500 .ct_attrs = uvc_attrs,
2501 .ct_owner = THIS_MODULE,
2502 },
2503 .name = "",
2504 .children = (const struct uvcg_config_group_type*[]) {
2505 &uvcg_control_grp_type,
2506 &uvcg_streaming_grp_type,
2507 NULL,
2508 },
2509 };
2510
uvcg_attach_configfs(struct f_uvc_opts * opts)2511 int uvcg_attach_configfs(struct f_uvc_opts *opts)
2512 {
2513 int ret;
2514
2515 config_group_init_type_name(&opts->func_inst.group, uvc_func_type.name,
2516 &uvc_func_type.type);
2517
2518 ret = uvcg_config_create_children(&opts->func_inst.group,
2519 &uvc_func_type);
2520 if (ret < 0)
2521 config_group_put(&opts->func_inst.group);
2522
2523 return ret;
2524 }
2525