Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 "uvc_configfs.h"
14
15#include <linux/sort.h>
16#include <linux/usb/video.h>
17
18/* -----------------------------------------------------------------------------
19 * Global Utility Structures and Macros
20 */
21
22#define UVC_ATTR(prefix, cname, aname) \
23static struct configfs_attribute prefix##attr_##cname = { \
24 .ca_name = __stringify(aname), \
25 .ca_mode = S_IRUGO | S_IWUGO, \
26 .ca_owner = THIS_MODULE, \
27 .show = prefix##cname##_show, \
28 .store = prefix##cname##_store, \
29}
30
31#define UVC_ATTR_RO(prefix, cname, aname) \
32static struct configfs_attribute prefix##attr_##cname = { \
33 .ca_name = __stringify(aname), \
34 .ca_mode = S_IRUGO, \
35 .ca_owner = THIS_MODULE, \
36 .show = prefix##cname##_show, \
37}
38
39#define le8_to_cpu(x) (x)
40#define cpu_to_le8(x) (x)
41
42static int uvcg_config_compare_u32(const void *l, const void *r)
43{
44 u32 li = *(const u32 *)l;
45 u32 ri = *(const u32 *)r;
46
47 return li < ri ? -1 : li == ri ? 0 : 1;
48}
49
50static inline int __uvcg_count_item_entries(char *buf, void *priv, unsigned int size)
51{
52 ++*((int *)priv);
53 return 0;
54}
55
56static inline int __uvcg_fill_item_entries(char *buf, void *priv, unsigned int size)
57{
58 unsigned int num;
59 u8 **values;
60 int ret;
61
62 ret = kstrtouint(buf, 0, &num);
63 if (ret)
64 return ret;
65
66 if (num != (num & GENMASK((size * 8) - 1, 0)))
67 return -ERANGE;
68
69 values = priv;
70 memcpy(*values, &num, size);
71 *values += size;
72
73 return 0;
74}
75
76static int __uvcg_iter_item_entries(const char *page, size_t len,
77 int (*fun)(char *, void *, unsigned int),
78 void *priv, unsigned int size)
79{
80 /* sign, base 2 representation, newline, terminator */
81 unsigned int bufsize = 1 + size * 8 + 1 + 1;
82 const char *pg = page;
83 int i, ret = 0;
84 char *buf;
85
86 if (!fun)
87 return -EINVAL;
88
89 buf = kzalloc(bufsize, GFP_KERNEL);
90 if (!buf)
91 return -ENOMEM;
92
93 while (pg - page < len) {
94 i = 0;
95 while (i < sizeof(buf) && (pg - page < len) &&
96 *pg != '\0' && *pg != '\n')
97 buf[i++] = *pg++;
98 if (i == sizeof(buf)) {
99 ret = -EINVAL;
100 goto out_free_buf;
101 }
102 while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
103 ++pg;
104 buf[i] = '\0';
105 ret = fun(buf, priv, size);
106 if (ret)
107 goto out_free_buf;
108 }
109
110out_free_buf:
111 kfree(buf);
112 return ret;
113}
114
115struct uvcg_config_group_type {
116 struct config_item_type type;
117 const char *name;
118 const struct uvcg_config_group_type **children;
119 int (*create_children)(struct config_group *group);
120};
121
122static void uvcg_config_item_release(struct config_item *item)
123{
124 struct config_group *group = to_config_group(item);
125
126 kfree(group);
127}
128
129static struct configfs_item_operations uvcg_config_item_ops = {
130 .release = uvcg_config_item_release,
131};
132
133static int uvcg_config_create_group(struct config_group *parent,
134 const struct uvcg_config_group_type *type);
135
136static int uvcg_config_create_children(struct config_group *group,
137 const struct uvcg_config_group_type *type)
138{
139 const struct uvcg_config_group_type **child;
140 int ret;
141
142 if (type->create_children)
143 return type->create_children(group);
144
145 for (child = type->children; child && *child; ++child) {
146 ret = uvcg_config_create_group(group, *child);
147 if (ret < 0)
148 return ret;
149 }
150
151 return 0;
152}
153
154static int uvcg_config_create_group(struct config_group *parent,
155 const struct uvcg_config_group_type *type)
156{
157 struct config_group *group;
158
159 group = kzalloc(sizeof(*group), GFP_KERNEL);
160 if (!group)
161 return -ENOMEM;
162
163 config_group_init_type_name(group, type->name, &type->type);
164 configfs_add_default_group(group, parent);
165
166 return uvcg_config_create_children(group, type);
167}
168
169static void uvcg_config_remove_children(struct config_group *group)
170{
171 struct config_group *child, *n;
172
173 list_for_each_entry_safe(child, n, &group->default_groups, group_entry) {
174 list_del(&child->group_entry);
175 uvcg_config_remove_children(child);
176 config_item_put(&child->cg_item);
177 }
178}
179
180/* -----------------------------------------------------------------------------
181 * control/header/<NAME>
182 * control/header
183 */
184
185#define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \
186static ssize_t uvcg_control_header_##cname##_show( \
187 struct config_item *item, char *page) \
188{ \
189 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
190 struct f_uvc_opts *opts; \
191 struct config_item *opts_item; \
192 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
193 int result; \
194 \
195 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
196 \
197 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
198 opts = to_f_uvc_opts(opts_item); \
199 \
200 mutex_lock(&opts->lock); \
201 result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\
202 mutex_unlock(&opts->lock); \
203 \
204 mutex_unlock(su_mutex); \
205 return result; \
206} \
207 \
208static ssize_t \
209uvcg_control_header_##cname##_store(struct config_item *item, \
210 const char *page, size_t len) \
211{ \
212 struct uvcg_control_header *ch = to_uvcg_control_header(item); \
213 struct f_uvc_opts *opts; \
214 struct config_item *opts_item; \
215 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
216 int ret; \
217 u##bits num; \
218 \
219 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
220 \
221 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \
222 opts = to_f_uvc_opts(opts_item); \
223 \
224 mutex_lock(&opts->lock); \
225 if (ch->linked || opts->refcnt) { \
226 ret = -EBUSY; \
227 goto end; \
228 } \
229 \
230 ret = kstrtou##bits(page, 0, &num); \
231 if (ret) \
232 goto end; \
233 \
234 if (num > limit) { \
235 ret = -EINVAL; \
236 goto end; \
237 } \
238 ch->desc.aname = cpu_to_le##bits(num); \
239 ret = len; \
240end: \
241 mutex_unlock(&opts->lock); \
242 mutex_unlock(su_mutex); \
243 return ret; \
244} \
245 \
246UVC_ATTR(uvcg_control_header_, cname, aname)
247
248UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, 16, 0xffff);
249
250UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, 32, 0x7fffffff);
251
252#undef UVCG_CTRL_HDR_ATTR
253
254static struct configfs_attribute *uvcg_control_header_attrs[] = {
255 &uvcg_control_header_attr_bcd_uvc,
256 &uvcg_control_header_attr_dw_clock_frequency,
257 NULL,
258};
259
260static const struct config_item_type uvcg_control_header_type = {
261 .ct_item_ops = &uvcg_config_item_ops,
262 .ct_attrs = uvcg_control_header_attrs,
263 .ct_owner = THIS_MODULE,
264};
265
266static struct config_item *uvcg_control_header_make(struct config_group *group,
267 const char *name)
268{
269 struct uvcg_control_header *h;
270
271 h = kzalloc(sizeof(*h), GFP_KERNEL);
272 if (!h)
273 return ERR_PTR(-ENOMEM);
274
275 h->desc.bLength = UVC_DT_HEADER_SIZE(1);
276 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
277 h->desc.bDescriptorSubType = UVC_VC_HEADER;
278 h->desc.bcdUVC = cpu_to_le16(0x0110);
279 h->desc.dwClockFrequency = cpu_to_le32(48000000);
280
281 config_item_init_type_name(&h->item, name, &uvcg_control_header_type);
282
283 return &h->item;
284}
285
286static struct configfs_group_operations uvcg_control_header_grp_ops = {
287 .make_item = uvcg_control_header_make,
288};
289
290static const struct uvcg_config_group_type uvcg_control_header_grp_type = {
291 .type = {
292 .ct_item_ops = &uvcg_config_item_ops,
293 .ct_group_ops = &uvcg_control_header_grp_ops,
294 .ct_owner = THIS_MODULE,
295 },
296 .name = "header",
297};
298
299/* -----------------------------------------------------------------------------
300 * control/processing/default
301 */
302
303#define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, bits) \
304static ssize_t uvcg_default_processing_##cname##_show( \
305 struct config_item *item, char *page) \
306{ \
307 struct config_group *group = to_config_group(item); \
308 struct f_uvc_opts *opts; \
309 struct config_item *opts_item; \
310 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
311 struct uvc_processing_unit_descriptor *pd; \
312 int result; \
313 \
314 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
315 \
316 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
317 opts = to_f_uvc_opts(opts_item); \
318 pd = &opts->uvc_processing; \
319 \
320 mutex_lock(&opts->lock); \
321 result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \
322 mutex_unlock(&opts->lock); \
323 \
324 mutex_unlock(su_mutex); \
325 return result; \
326} \
327 \
328UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
329
330UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, 8);
331UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, 8);
332UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, 16);
333UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8);
334
335#undef UVCG_DEFAULT_PROCESSING_ATTR
336
337static ssize_t uvcg_default_processing_bm_controls_show(
338 struct config_item *item, char *page)
339{
340 struct config_group *group = to_config_group(item);
341 struct f_uvc_opts *opts;
342 struct config_item *opts_item;
343 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
344 struct uvc_processing_unit_descriptor *pd;
345 int result, i;
346 char *pg = page;
347
348 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
349
350 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
351 opts = to_f_uvc_opts(opts_item);
352 pd = &opts->uvc_processing;
353
354 mutex_lock(&opts->lock);
355 for (result = 0, i = 0; i < pd->bControlSize; ++i) {
356 result += sprintf(pg, "%u\n", pd->bmControls[i]);
357 pg = page + result;
358 }
359 mutex_unlock(&opts->lock);
360
361 mutex_unlock(su_mutex);
362
363 return result;
364}
365
366UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
367
368static struct configfs_attribute *uvcg_default_processing_attrs[] = {
369 &uvcg_default_processing_attr_b_unit_id,
370 &uvcg_default_processing_attr_b_source_id,
371 &uvcg_default_processing_attr_w_max_multiplier,
372 &uvcg_default_processing_attr_bm_controls,
373 &uvcg_default_processing_attr_i_processing,
374 NULL,
375};
376
377static const struct uvcg_config_group_type uvcg_default_processing_type = {
378 .type = {
379 .ct_item_ops = &uvcg_config_item_ops,
380 .ct_attrs = uvcg_default_processing_attrs,
381 .ct_owner = THIS_MODULE,
382 },
383 .name = "default",
384};
385
386/* -----------------------------------------------------------------------------
387 * control/processing
388 */
389
390static const struct uvcg_config_group_type uvcg_processing_grp_type = {
391 .type = {
392 .ct_item_ops = &uvcg_config_item_ops,
393 .ct_owner = THIS_MODULE,
394 },
395 .name = "processing",
396 .children = (const struct uvcg_config_group_type*[]) {
397 &uvcg_default_processing_type,
398 NULL,
399 },
400};
401
402/* -----------------------------------------------------------------------------
403 * control/terminal/camera/default
404 */
405
406#define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, bits) \
407static ssize_t uvcg_default_camera_##cname##_show( \
408 struct config_item *item, char *page) \
409{ \
410 struct config_group *group = to_config_group(item); \
411 struct f_uvc_opts *opts; \
412 struct config_item *opts_item; \
413 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
414 struct uvc_camera_terminal_descriptor *cd; \
415 int result; \
416 \
417 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
418 \
419 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \
420 ci_parent; \
421 opts = to_f_uvc_opts(opts_item); \
422 cd = &opts->uvc_camera_terminal; \
423 \
424 mutex_lock(&opts->lock); \
425 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
426 mutex_unlock(&opts->lock); \
427 \
428 mutex_unlock(su_mutex); \
429 \
430 return result; \
431} \
432 \
433UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
434
435UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, 8);
436UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, 16);
437UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, 8);
438UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, 8);
439UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
440 16);
441UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
442 16);
443UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
444 16);
445
446#undef UVCG_DEFAULT_CAMERA_ATTR
447
448static ssize_t uvcg_default_camera_bm_controls_show(
449 struct config_item *item, char *page)
450{
451 struct config_group *group = to_config_group(item);
452 struct f_uvc_opts *opts;
453 struct config_item *opts_item;
454 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
455 struct uvc_camera_terminal_descriptor *cd;
456 int result, i;
457 char *pg = page;
458
459 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
460
461 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
462 ci_parent;
463 opts = to_f_uvc_opts(opts_item);
464 cd = &opts->uvc_camera_terminal;
465
466 mutex_lock(&opts->lock);
467 for (result = 0, i = 0; i < cd->bControlSize; ++i) {
468 result += sprintf(pg, "%u\n", cd->bmControls[i]);
469 pg = page + result;
470 }
471 mutex_unlock(&opts->lock);
472
473 mutex_unlock(su_mutex);
474 return result;
475}
476
477UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
478
479static struct configfs_attribute *uvcg_default_camera_attrs[] = {
480 &uvcg_default_camera_attr_b_terminal_id,
481 &uvcg_default_camera_attr_w_terminal_type,
482 &uvcg_default_camera_attr_b_assoc_terminal,
483 &uvcg_default_camera_attr_i_terminal,
484 &uvcg_default_camera_attr_w_objective_focal_length_min,
485 &uvcg_default_camera_attr_w_objective_focal_length_max,
486 &uvcg_default_camera_attr_w_ocular_focal_length,
487 &uvcg_default_camera_attr_bm_controls,
488 NULL,
489};
490
491static const struct uvcg_config_group_type uvcg_default_camera_type = {
492 .type = {
493 .ct_item_ops = &uvcg_config_item_ops,
494 .ct_attrs = uvcg_default_camera_attrs,
495 .ct_owner = THIS_MODULE,
496 },
497 .name = "default",
498};
499
500/* -----------------------------------------------------------------------------
501 * control/terminal/camera
502 */
503
504static const struct uvcg_config_group_type uvcg_camera_grp_type = {
505 .type = {
506 .ct_item_ops = &uvcg_config_item_ops,
507 .ct_owner = THIS_MODULE,
508 },
509 .name = "camera",
510 .children = (const struct uvcg_config_group_type*[]) {
511 &uvcg_default_camera_type,
512 NULL,
513 },
514};
515
516/* -----------------------------------------------------------------------------
517 * control/terminal/output/default
518 */
519
520#define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, bits) \
521static ssize_t uvcg_default_output_##cname##_show( \
522 struct config_item *item, char *page) \
523{ \
524 struct config_group *group = to_config_group(item); \
525 struct f_uvc_opts *opts; \
526 struct config_item *opts_item; \
527 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
528 struct uvc_output_terminal_descriptor *cd; \
529 int result; \
530 \
531 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
532 \
533 opts_item = group->cg_item.ci_parent->ci_parent-> \
534 ci_parent->ci_parent; \
535 opts = to_f_uvc_opts(opts_item); \
536 cd = &opts->uvc_output_terminal; \
537 \
538 mutex_lock(&opts->lock); \
539 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
540 mutex_unlock(&opts->lock); \
541 \
542 mutex_unlock(su_mutex); \
543 \
544 return result; \
545} \
546 \
547UVC_ATTR_RO(uvcg_default_output_, cname, aname)
548
549UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, 8);
550UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, 16);
551UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, 8);
552UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, 8);
553
554#undef UVCG_DEFAULT_OUTPUT_ATTR
555
556static ssize_t uvcg_default_output_b_source_id_show(struct config_item *item,
557 char *page)
558{
559 struct config_group *group = to_config_group(item);
560 struct f_uvc_opts *opts;
561 struct config_item *opts_item;
562 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
563 struct uvc_output_terminal_descriptor *cd;
564 int result;
565
566 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
567
568 opts_item = group->cg_item.ci_parent->ci_parent->
569 ci_parent->ci_parent;
570 opts = to_f_uvc_opts(opts_item);
571 cd = &opts->uvc_output_terminal;
572
573 mutex_lock(&opts->lock);
574 result = sprintf(page, "%u\n", le8_to_cpu(cd->bSourceID));
575 mutex_unlock(&opts->lock);
576
577 mutex_unlock(su_mutex);
578
579 return result;
580}
581
582static ssize_t uvcg_default_output_b_source_id_store(struct config_item *item,
583 const char *page, size_t len)
584{
585 struct config_group *group = to_config_group(item);
586 struct f_uvc_opts *opts;
587 struct config_item *opts_item;
588 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
589 struct uvc_output_terminal_descriptor *cd;
590 int result;
591 u8 num;
592
593 result = kstrtou8(page, 0, &num);
594 if (result)
595 return result;
596
597 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
598
599 opts_item = group->cg_item.ci_parent->ci_parent->
600 ci_parent->ci_parent;
601 opts = to_f_uvc_opts(opts_item);
602 cd = &opts->uvc_output_terminal;
603
604 mutex_lock(&opts->lock);
605 cd->bSourceID = num;
606 mutex_unlock(&opts->lock);
607
608 mutex_unlock(su_mutex);
609
610 return len;
611}
612UVC_ATTR(uvcg_default_output_, b_source_id, bSourceID);
613
614static struct configfs_attribute *uvcg_default_output_attrs[] = {
615 &uvcg_default_output_attr_b_terminal_id,
616 &uvcg_default_output_attr_w_terminal_type,
617 &uvcg_default_output_attr_b_assoc_terminal,
618 &uvcg_default_output_attr_b_source_id,
619 &uvcg_default_output_attr_i_terminal,
620 NULL,
621};
622
623static const struct uvcg_config_group_type uvcg_default_output_type = {
624 .type = {
625 .ct_item_ops = &uvcg_config_item_ops,
626 .ct_attrs = uvcg_default_output_attrs,
627 .ct_owner = THIS_MODULE,
628 },
629 .name = "default",
630};
631
632/* -----------------------------------------------------------------------------
633 * control/terminal/output
634 */
635
636static const struct uvcg_config_group_type uvcg_output_grp_type = {
637 .type = {
638 .ct_item_ops = &uvcg_config_item_ops,
639 .ct_owner = THIS_MODULE,
640 },
641 .name = "output",
642 .children = (const struct uvcg_config_group_type*[]) {
643 &uvcg_default_output_type,
644 NULL,
645 },
646};
647
648/* -----------------------------------------------------------------------------
649 * control/terminal
650 */
651
652static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
653 .type = {
654 .ct_item_ops = &uvcg_config_item_ops,
655 .ct_owner = THIS_MODULE,
656 },
657 .name = "terminal",
658 .children = (const struct uvcg_config_group_type*[]) {
659 &uvcg_camera_grp_type,
660 &uvcg_output_grp_type,
661 NULL,
662 },
663};
664
665/* -----------------------------------------------------------------------------
666 * control/extensions
667 */
668
669#define UVCG_EXTENSION_ATTR(cname, aname, ro...) \
670static ssize_t uvcg_extension_##cname##_show(struct config_item *item, \
671 char *page) \
672{ \
673 struct config_group *group = to_config_group(item->ci_parent); \
674 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
675 struct uvcg_extension *xu = to_uvcg_extension(item); \
676 struct config_item *opts_item; \
677 struct f_uvc_opts *opts; \
678 int ret; \
679 \
680 mutex_lock(su_mutex); \
681 \
682 opts_item = item->ci_parent->ci_parent->ci_parent; \
683 opts = to_f_uvc_opts(opts_item); \
684 \
685 mutex_lock(&opts->lock); \
686 ret = sprintf(page, "%u\n", xu->desc.aname); \
687 mutex_unlock(&opts->lock); \
688 \
689 mutex_unlock(su_mutex); \
690 \
691 return ret; \
692} \
693UVC_ATTR##ro(uvcg_extension_, cname, aname)
694
695UVCG_EXTENSION_ATTR(b_length, bLength, _RO);
696UVCG_EXTENSION_ATTR(b_unit_id, bUnitID, _RO);
697UVCG_EXTENSION_ATTR(i_extension, iExtension, _RO);
698
699static ssize_t uvcg_extension_b_num_controls_store(struct config_item *item,
700 const char *page, size_t len)
701{
702 struct config_group *group = to_config_group(item->ci_parent);
703 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
704 struct uvcg_extension *xu = to_uvcg_extension(item);
705 struct config_item *opts_item;
706 struct f_uvc_opts *opts;
707 int ret;
708 u8 num;
709
710 ret = kstrtou8(page, 0, &num);
711 if (ret)
712 return ret;
713
714 mutex_lock(su_mutex);
715
716 opts_item = item->ci_parent->ci_parent->ci_parent;
717 opts = to_f_uvc_opts(opts_item);
718
719 mutex_lock(&opts->lock);
720 xu->desc.bNumControls = num;
721 mutex_unlock(&opts->lock);
722
723 mutex_unlock(su_mutex);
724
725 return len;
726}
727UVCG_EXTENSION_ATTR(b_num_controls, bNumControls);
728
729/*
730 * In addition to storing bNrInPins, this function needs to realloc the
731 * memory for the baSourceID array and additionally expand bLength.
732 */
733static ssize_t uvcg_extension_b_nr_in_pins_store(struct config_item *item,
734 const char *page, size_t len)
735{
736 struct config_group *group = to_config_group(item->ci_parent);
737 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
738 struct uvcg_extension *xu = to_uvcg_extension(item);
739 struct config_item *opts_item;
740 struct f_uvc_opts *opts;
741 void *tmp_buf;
742 int ret;
743 u8 num;
744
745 ret = kstrtou8(page, 0, &num);
746 if (ret)
747 return ret;
748
749 mutex_lock(su_mutex);
750
751 opts_item = item->ci_parent->ci_parent->ci_parent;
752 opts = to_f_uvc_opts(opts_item);
753
754 mutex_lock(&opts->lock);
755
756 if (num == xu->desc.bNrInPins) {
757 ret = len;
758 goto unlock;
759 }
760
761 tmp_buf = krealloc_array(xu->desc.baSourceID, num, sizeof(u8),
762 GFP_KERNEL | __GFP_ZERO);
763 if (!tmp_buf) {
764 ret = -ENOMEM;
765 goto unlock;
766 }
767
768 xu->desc.baSourceID = tmp_buf;
769 xu->desc.bNrInPins = num;
770 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins,
771 xu->desc.bControlSize);
772
773 ret = len;
774
775unlock:
776 mutex_unlock(&opts->lock);
777 mutex_unlock(su_mutex);
778 return ret;
779}
780UVCG_EXTENSION_ATTR(b_nr_in_pins, bNrInPins);
781
782/*
783 * In addition to storing bControlSize, this function needs to realloc the
784 * memory for the bmControls array and additionally expand bLength.
785 */
786static ssize_t uvcg_extension_b_control_size_store(struct config_item *item,
787 const char *page, size_t len)
788{
789 struct config_group *group = to_config_group(item->ci_parent);
790 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
791 struct uvcg_extension *xu = to_uvcg_extension(item);
792 struct config_item *opts_item;
793 struct f_uvc_opts *opts;
794 void *tmp_buf;
795 int ret;
796 u8 num;
797
798 ret = kstrtou8(page, 0, &num);
799 if (ret)
800 return ret;
801
802 mutex_lock(su_mutex);
803
804 opts_item = item->ci_parent->ci_parent->ci_parent;
805 opts = to_f_uvc_opts(opts_item);
806
807 mutex_lock(&opts->lock);
808
809 if (num == xu->desc.bControlSize) {
810 ret = len;
811 goto unlock;
812 }
813
814 tmp_buf = krealloc_array(xu->desc.bmControls, num, sizeof(u8),
815 GFP_KERNEL | __GFP_ZERO);
816 if (!tmp_buf) {
817 ret = -ENOMEM;
818 goto unlock;
819 }
820
821 xu->desc.bmControls = tmp_buf;
822 xu->desc.bControlSize = num;
823 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins,
824 xu->desc.bControlSize);
825
826 ret = len;
827
828unlock:
829 mutex_unlock(&opts->lock);
830 mutex_unlock(su_mutex);
831 return ret;
832}
833
834UVCG_EXTENSION_ATTR(b_control_size, bControlSize);
835
836static ssize_t uvcg_extension_guid_extension_code_show(struct config_item *item,
837 char *page)
838{
839 struct config_group *group = to_config_group(item->ci_parent);
840 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
841 struct uvcg_extension *xu = to_uvcg_extension(item);
842 struct config_item *opts_item;
843 struct f_uvc_opts *opts;
844
845 mutex_lock(su_mutex);
846
847 opts_item = item->ci_parent->ci_parent->ci_parent;
848 opts = to_f_uvc_opts(opts_item);
849
850 mutex_lock(&opts->lock);
851 memcpy(page, xu->desc.guidExtensionCode, sizeof(xu->desc.guidExtensionCode));
852 mutex_unlock(&opts->lock);
853
854 mutex_unlock(su_mutex);
855
856 return sizeof(xu->desc.guidExtensionCode);
857}
858
859static ssize_t uvcg_extension_guid_extension_code_store(struct config_item *item,
860 const char *page, size_t len)
861{
862 struct config_group *group = to_config_group(item->ci_parent);
863 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
864 struct uvcg_extension *xu = to_uvcg_extension(item);
865 struct config_item *opts_item;
866 struct f_uvc_opts *opts;
867 int ret;
868
869 mutex_lock(su_mutex);
870
871 opts_item = item->ci_parent->ci_parent->ci_parent;
872 opts = to_f_uvc_opts(opts_item);
873
874 mutex_lock(&opts->lock);
875 memcpy(xu->desc.guidExtensionCode, page,
876 min(sizeof(xu->desc.guidExtensionCode), len));
877 mutex_unlock(&opts->lock);
878
879 mutex_unlock(su_mutex);
880
881 ret = sizeof(xu->desc.guidExtensionCode);
882
883 return ret;
884}
885
886UVC_ATTR(uvcg_extension_, guid_extension_code, guidExtensionCode);
887
888static ssize_t uvcg_extension_ba_source_id_show(struct config_item *item,
889 char *page)
890{
891 struct config_group *group = to_config_group(item->ci_parent);
892 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
893 struct uvcg_extension *xu = to_uvcg_extension(item);
894 struct config_item *opts_item;
895 struct f_uvc_opts *opts;
896 char *pg = page;
897 int ret, i;
898
899 mutex_lock(su_mutex);
900
901 opts_item = item->ci_parent->ci_parent->ci_parent;
902 opts = to_f_uvc_opts(opts_item);
903
904 mutex_lock(&opts->lock);
905 for (ret = 0, i = 0; i < xu->desc.bNrInPins; ++i) {
906 ret += sprintf(pg, "%u\n", xu->desc.baSourceID[i]);
907 pg = page + ret;
908 }
909 mutex_unlock(&opts->lock);
910
911 mutex_unlock(su_mutex);
912
913 return ret;
914}
915
916static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item,
917 const char *page, size_t len)
918{
919 struct config_group *group = to_config_group(item->ci_parent);
920 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
921 struct uvcg_extension *xu = to_uvcg_extension(item);
922 struct config_item *opts_item;
923 struct f_uvc_opts *opts;
924 u8 *source_ids, *iter;
925 int ret, n = 0;
926
927 mutex_lock(su_mutex);
928
929 opts_item = item->ci_parent->ci_parent->ci_parent;
930 opts = to_f_uvc_opts(opts_item);
931
932 mutex_lock(&opts->lock);
933
934 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n,
935 sizeof(u8));
936 if (ret)
937 goto unlock;
938
939 iter = source_ids = kcalloc(n, sizeof(u8), GFP_KERNEL);
940 if (!source_ids) {
941 ret = -ENOMEM;
942 goto unlock;
943 }
944
945 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &iter,
946 sizeof(u8));
947 if (ret) {
948 kfree(source_ids);
949 goto unlock;
950 }
951
952 kfree(xu->desc.baSourceID);
953 xu->desc.baSourceID = source_ids;
954 xu->desc.bNrInPins = n;
955 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins,
956 xu->desc.bControlSize);
957
958 ret = len;
959
960unlock:
961 mutex_unlock(&opts->lock);
962 mutex_unlock(su_mutex);
963 return ret;
964}
965UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID);
966
967static ssize_t uvcg_extension_bm_controls_show(struct config_item *item,
968 char *page)
969{
970 struct config_group *group = to_config_group(item->ci_parent);
971 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
972 struct uvcg_extension *xu = to_uvcg_extension(item);
973 struct config_item *opts_item;
974 struct f_uvc_opts *opts;
975 char *pg = page;
976 int ret, i;
977
978 mutex_lock(su_mutex);
979
980 opts_item = item->ci_parent->ci_parent->ci_parent;
981 opts = to_f_uvc_opts(opts_item);
982
983 mutex_lock(&opts->lock);
984 for (ret = 0, i = 0; i < xu->desc.bControlSize; ++i) {
985 ret += sprintf(pg, "0x%02x\n", xu->desc.bmControls[i]);
986 pg = page + ret;
987 }
988 mutex_unlock(&opts->lock);
989
990 mutex_unlock(su_mutex);
991
992 return ret;
993}
994
995static ssize_t uvcg_extension_bm_controls_store(struct config_item *item,
996 const char *page, size_t len)
997{
998 struct config_group *group = to_config_group(item->ci_parent);
999 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
1000 struct uvcg_extension *xu = to_uvcg_extension(item);
1001 struct config_item *opts_item;
1002 struct f_uvc_opts *opts;
1003 u8 *bm_controls, *iter;
1004 int ret, n = 0;
1005
1006 mutex_lock(su_mutex);
1007
1008 opts_item = item->ci_parent->ci_parent->ci_parent;
1009 opts = to_f_uvc_opts(opts_item);
1010
1011 mutex_lock(&opts->lock);
1012
1013 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n,
1014 sizeof(u8));
1015 if (ret)
1016 goto unlock;
1017
1018 iter = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL);
1019 if (!bm_controls) {
1020 ret = -ENOMEM;
1021 goto unlock;
1022 }
1023
1024 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &iter,
1025 sizeof(u8));
1026 if (ret) {
1027 kfree(bm_controls);
1028 goto unlock;
1029 }
1030
1031 kfree(xu->desc.bmControls);
1032 xu->desc.bmControls = bm_controls;
1033 xu->desc.bControlSize = n;
1034 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins,
1035 xu->desc.bControlSize);
1036
1037 ret = len;
1038
1039unlock:
1040 mutex_unlock(&opts->lock);
1041 mutex_unlock(su_mutex);
1042 return ret;
1043}
1044
1045UVC_ATTR(uvcg_extension_, bm_controls, bmControls);
1046
1047static struct configfs_attribute *uvcg_extension_attrs[] = {
1048 &uvcg_extension_attr_b_length,
1049 &uvcg_extension_attr_b_unit_id,
1050 &uvcg_extension_attr_b_num_controls,
1051 &uvcg_extension_attr_b_nr_in_pins,
1052 &uvcg_extension_attr_b_control_size,
1053 &uvcg_extension_attr_guid_extension_code,
1054 &uvcg_extension_attr_ba_source_id,
1055 &uvcg_extension_attr_bm_controls,
1056 &uvcg_extension_attr_i_extension,
1057 NULL,
1058};
1059
1060static void uvcg_extension_release(struct config_item *item)
1061{
1062 struct uvcg_extension *xu = container_of(item, struct uvcg_extension, item);
1063
1064 kfree(xu);
1065}
1066
1067static int uvcg_extension_allow_link(struct config_item *src, struct config_item *tgt)
1068{
1069 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1070 struct uvcg_extension *xu = to_uvcg_extension(src);
1071 struct config_item *gadget_item;
1072 struct gadget_string *string;
1073 struct config_item *strings;
1074 int ret = 0;
1075
1076 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1077
1078 /* Validate that the target of the link is an entry in strings/<langid> */
1079 gadget_item = src->ci_parent->ci_parent->ci_parent->ci_parent->ci_parent;
1080 strings = config_group_find_item(to_config_group(gadget_item), "strings");
1081 if (!strings || tgt->ci_parent->ci_parent != strings) {
1082 ret = -EINVAL;
1083 goto put_strings;
1084 }
1085
1086 string = to_gadget_string(tgt);
1087 xu->string_descriptor_index = string->usb_string.id;
1088
1089put_strings:
1090 config_item_put(strings);
1091 mutex_unlock(su_mutex);
1092
1093 return ret;
1094}
1095
1096static void uvcg_extension_drop_link(struct config_item *src, struct config_item *tgt)
1097{
1098 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1099 struct uvcg_extension *xu = to_uvcg_extension(src);
1100 struct config_item *opts_item;
1101 struct f_uvc_opts *opts;
1102
1103 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1104
1105 opts_item = src->ci_parent->ci_parent->ci_parent;
1106 opts = to_f_uvc_opts(opts_item);
1107
1108 mutex_lock(&opts->lock);
1109
1110 xu->string_descriptor_index = 0;
1111
1112 mutex_unlock(&opts->lock);
1113
1114 mutex_unlock(su_mutex);
1115}
1116
1117static struct configfs_item_operations uvcg_extension_item_ops = {
1118 .release = uvcg_extension_release,
1119 .allow_link = uvcg_extension_allow_link,
1120 .drop_link = uvcg_extension_drop_link,
1121};
1122
1123static const struct config_item_type uvcg_extension_type = {
1124 .ct_item_ops = &uvcg_extension_item_ops,
1125 .ct_attrs = uvcg_extension_attrs,
1126 .ct_owner = THIS_MODULE,
1127};
1128
1129static void uvcg_extension_drop(struct config_group *group, struct config_item *item)
1130{
1131 struct uvcg_extension *xu = container_of(item, struct uvcg_extension, item);
1132 struct config_item *opts_item;
1133 struct f_uvc_opts *opts;
1134
1135 opts_item = group->cg_item.ci_parent->ci_parent;
1136 opts = to_f_uvc_opts(opts_item);
1137
1138 mutex_lock(&opts->lock);
1139
1140 config_item_put(item);
1141 list_del(&xu->list);
1142 kfree(xu->desc.baSourceID);
1143 kfree(xu->desc.bmControls);
1144
1145 mutex_unlock(&opts->lock);
1146}
1147
1148static struct config_item *uvcg_extension_make(struct config_group *group, const char *name)
1149{
1150 struct config_item *opts_item;
1151 struct uvcg_extension *xu;
1152 struct f_uvc_opts *opts;
1153
1154 opts_item = group->cg_item.ci_parent->ci_parent;
1155 opts = to_f_uvc_opts(opts_item);
1156
1157 xu = kzalloc(sizeof(*xu), GFP_KERNEL);
1158 if (!xu)
1159 return ERR_PTR(-ENOMEM);
1160
1161 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(0, 0);
1162 xu->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1163 xu->desc.bDescriptorSubType = UVC_VC_EXTENSION_UNIT;
1164 xu->desc.bNumControls = 0;
1165 xu->desc.bNrInPins = 0;
1166 xu->desc.baSourceID = NULL;
1167 xu->desc.bControlSize = 0;
1168 xu->desc.bmControls = NULL;
1169
1170 mutex_lock(&opts->lock);
1171
1172 xu->desc.bUnitID = ++opts->last_unit_id;
1173
1174 config_item_init_type_name(&xu->item, name, &uvcg_extension_type);
1175 list_add_tail(&xu->list, &opts->extension_units);
1176
1177 mutex_unlock(&opts->lock);
1178
1179 return &xu->item;
1180}
1181
1182static struct configfs_group_operations uvcg_extensions_grp_ops = {
1183 .make_item = uvcg_extension_make,
1184 .drop_item = uvcg_extension_drop,
1185};
1186
1187static const struct uvcg_config_group_type uvcg_extensions_grp_type = {
1188 .type = {
1189 .ct_item_ops = &uvcg_config_item_ops,
1190 .ct_group_ops = &uvcg_extensions_grp_ops,
1191 .ct_owner = THIS_MODULE,
1192 },
1193 .name = "extensions",
1194};
1195
1196/* -----------------------------------------------------------------------------
1197 * control/class/{fs|ss}
1198 */
1199
1200struct uvcg_control_class_group {
1201 struct config_group group;
1202 const char *name;
1203};
1204
1205static inline struct uvc_descriptor_header
1206**uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
1207{
1208 struct uvcg_control_class_group *group =
1209 container_of(i, struct uvcg_control_class_group,
1210 group.cg_item);
1211
1212 if (!strcmp(group->name, "fs"))
1213 return o->uvc_fs_control_cls;
1214
1215 if (!strcmp(group->name, "ss"))
1216 return o->uvc_ss_control_cls;
1217
1218 return NULL;
1219}
1220
1221static int uvcg_control_class_allow_link(struct config_item *src,
1222 struct config_item *target)
1223{
1224 struct config_item *control, *header;
1225 struct f_uvc_opts *opts;
1226 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1227 struct uvc_descriptor_header **class_array;
1228 struct uvcg_control_header *target_hdr;
1229 int ret = -EINVAL;
1230
1231 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1232
1233 control = src->ci_parent->ci_parent;
1234 header = config_group_find_item(to_config_group(control), "header");
1235 if (!header || target->ci_parent != header)
1236 goto out;
1237
1238 opts = to_f_uvc_opts(control->ci_parent);
1239
1240 mutex_lock(&opts->lock);
1241
1242 class_array = uvcg_get_ctl_class_arr(src, opts);
1243 if (!class_array)
1244 goto unlock;
1245 if (opts->refcnt || class_array[0]) {
1246 ret = -EBUSY;
1247 goto unlock;
1248 }
1249
1250 target_hdr = to_uvcg_control_header(target);
1251 ++target_hdr->linked;
1252 class_array[0] = (struct uvc_descriptor_header *)&target_hdr->desc;
1253 ret = 0;
1254
1255unlock:
1256 mutex_unlock(&opts->lock);
1257out:
1258 config_item_put(header);
1259 mutex_unlock(su_mutex);
1260 return ret;
1261}
1262
1263static void uvcg_control_class_drop_link(struct config_item *src,
1264 struct config_item *target)
1265{
1266 struct config_item *control, *header;
1267 struct f_uvc_opts *opts;
1268 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1269 struct uvc_descriptor_header **class_array;
1270 struct uvcg_control_header *target_hdr;
1271
1272 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1273
1274 control = src->ci_parent->ci_parent;
1275 header = config_group_find_item(to_config_group(control), "header");
1276 if (!header || target->ci_parent != header)
1277 goto out;
1278
1279 opts = to_f_uvc_opts(control->ci_parent);
1280
1281 mutex_lock(&opts->lock);
1282
1283 class_array = uvcg_get_ctl_class_arr(src, opts);
1284 if (!class_array || opts->refcnt)
1285 goto unlock;
1286
1287 target_hdr = to_uvcg_control_header(target);
1288 --target_hdr->linked;
1289 class_array[0] = NULL;
1290
1291unlock:
1292 mutex_unlock(&opts->lock);
1293out:
1294 config_item_put(header);
1295 mutex_unlock(su_mutex);
1296}
1297
1298static struct configfs_item_operations uvcg_control_class_item_ops = {
1299 .release = uvcg_config_item_release,
1300 .allow_link = uvcg_control_class_allow_link,
1301 .drop_link = uvcg_control_class_drop_link,
1302};
1303
1304static const struct config_item_type uvcg_control_class_type = {
1305 .ct_item_ops = &uvcg_control_class_item_ops,
1306 .ct_owner = THIS_MODULE,
1307};
1308
1309/* -----------------------------------------------------------------------------
1310 * control/class
1311 */
1312
1313static int uvcg_control_class_create_children(struct config_group *parent)
1314{
1315 static const char * const names[] = { "fs", "ss" };
1316 unsigned int i;
1317
1318 for (i = 0; i < ARRAY_SIZE(names); ++i) {
1319 struct uvcg_control_class_group *group;
1320
1321 group = kzalloc(sizeof(*group), GFP_KERNEL);
1322 if (!group)
1323 return -ENOMEM;
1324
1325 group->name = names[i];
1326
1327 config_group_init_type_name(&group->group, group->name,
1328 &uvcg_control_class_type);
1329 configfs_add_default_group(&group->group, parent);
1330 }
1331
1332 return 0;
1333}
1334
1335static const struct uvcg_config_group_type uvcg_control_class_grp_type = {
1336 .type = {
1337 .ct_item_ops = &uvcg_config_item_ops,
1338 .ct_owner = THIS_MODULE,
1339 },
1340 .name = "class",
1341 .create_children = uvcg_control_class_create_children,
1342};
1343
1344/* -----------------------------------------------------------------------------
1345 * control
1346 */
1347
1348static ssize_t uvcg_default_control_b_interface_number_show(
1349 struct config_item *item, char *page)
1350{
1351 struct config_group *group = to_config_group(item);
1352 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
1353 struct config_item *opts_item;
1354 struct f_uvc_opts *opts;
1355 int result = 0;
1356
1357 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1358
1359 opts_item = item->ci_parent;
1360 opts = to_f_uvc_opts(opts_item);
1361
1362 mutex_lock(&opts->lock);
1363 result += sprintf(page, "%u\n", opts->control_interface);
1364 mutex_unlock(&opts->lock);
1365
1366 mutex_unlock(su_mutex);
1367
1368 return result;
1369}
1370
1371UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
1372
1373static ssize_t uvcg_default_control_enable_interrupt_ep_show(
1374 struct config_item *item, char *page)
1375{
1376 struct config_group *group = to_config_group(item);
1377 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
1378 struct config_item *opts_item;
1379 struct f_uvc_opts *opts;
1380 int result = 0;
1381
1382 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1383
1384 opts_item = item->ci_parent;
1385 opts = to_f_uvc_opts(opts_item);
1386
1387 mutex_lock(&opts->lock);
1388 result += sprintf(page, "%u\n", opts->enable_interrupt_ep);
1389 mutex_unlock(&opts->lock);
1390
1391 mutex_unlock(su_mutex);
1392
1393 return result;
1394}
1395
1396static ssize_t uvcg_default_control_enable_interrupt_ep_store(
1397 struct config_item *item, const char *page, size_t len)
1398{
1399 struct config_group *group = to_config_group(item);
1400 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
1401 struct config_item *opts_item;
1402 struct f_uvc_opts *opts;
1403 ssize_t ret;
1404 u8 num;
1405
1406 ret = kstrtou8(page, 0, &num);
1407 if (ret)
1408 return ret;
1409
1410 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1411
1412 opts_item = item->ci_parent;
1413 opts = to_f_uvc_opts(opts_item);
1414
1415 mutex_lock(&opts->lock);
1416 opts->enable_interrupt_ep = num;
1417 mutex_unlock(&opts->lock);
1418
1419 mutex_unlock(su_mutex);
1420
1421 return len;
1422}
1423UVC_ATTR(uvcg_default_control_, enable_interrupt_ep, enable_interrupt_ep);
1424
1425static struct configfs_attribute *uvcg_default_control_attrs[] = {
1426 &uvcg_default_control_attr_b_interface_number,
1427 &uvcg_default_control_attr_enable_interrupt_ep,
1428 NULL,
1429};
1430
1431static const struct uvcg_config_group_type uvcg_control_grp_type = {
1432 .type = {
1433 .ct_item_ops = &uvcg_config_item_ops,
1434 .ct_attrs = uvcg_default_control_attrs,
1435 .ct_owner = THIS_MODULE,
1436 },
1437 .name = "control",
1438 .children = (const struct uvcg_config_group_type*[]) {
1439 &uvcg_control_header_grp_type,
1440 &uvcg_processing_grp_type,
1441 &uvcg_terminal_grp_type,
1442 &uvcg_control_class_grp_type,
1443 &uvcg_extensions_grp_type,
1444 NULL,
1445 },
1446};
1447
1448/* -----------------------------------------------------------------------------
1449 * streaming/uncompressed
1450 * streaming/mjpeg
1451 */
1452
1453static const char * const uvcg_format_names[] = {
1454 "uncompressed",
1455 "mjpeg",
1456};
1457
1458static struct uvcg_color_matching *
1459uvcg_format_get_default_color_match(struct config_item *streaming)
1460{
1461 struct config_item *color_matching_item, *cm_default;
1462 struct uvcg_color_matching *color_match;
1463
1464 color_matching_item = config_group_find_item(to_config_group(streaming),
1465 "color_matching");
1466 if (!color_matching_item)
1467 return NULL;
1468
1469 cm_default = config_group_find_item(to_config_group(color_matching_item),
1470 "default");
1471 config_item_put(color_matching_item);
1472 if (!cm_default)
1473 return NULL;
1474
1475 color_match = to_uvcg_color_matching(to_config_group(cm_default));
1476 config_item_put(cm_default);
1477
1478 return color_match;
1479}
1480
1481static int uvcg_format_allow_link(struct config_item *src, struct config_item *tgt)
1482{
1483 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1484 struct uvcg_color_matching *color_matching_desc;
1485 struct config_item *streaming, *color_matching;
1486 struct uvcg_format *fmt;
1487 int ret = 0;
1488
1489 mutex_lock(su_mutex);
1490
1491 streaming = src->ci_parent->ci_parent;
1492 color_matching = config_group_find_item(to_config_group(streaming), "color_matching");
1493 if (!color_matching || color_matching != tgt->ci_parent) {
1494 ret = -EINVAL;
1495 goto out_put_cm;
1496 }
1497
1498 fmt = to_uvcg_format(src);
1499
1500 /*
1501 * There's always a color matching descriptor associated with the format
1502 * but without a symlink it should only ever be the default one. If it's
1503 * not the default, there's already a symlink and we should bail out.
1504 */
1505 color_matching_desc = uvcg_format_get_default_color_match(streaming);
1506 if (fmt->color_matching != color_matching_desc) {
1507 ret = -EBUSY;
1508 goto out_put_cm;
1509 }
1510
1511 color_matching_desc->refcnt--;
1512
1513 color_matching_desc = to_uvcg_color_matching(to_config_group(tgt));
1514 fmt->color_matching = color_matching_desc;
1515 color_matching_desc->refcnt++;
1516
1517out_put_cm:
1518 config_item_put(color_matching);
1519 mutex_unlock(su_mutex);
1520
1521 return ret;
1522}
1523
1524static void uvcg_format_drop_link(struct config_item *src, struct config_item *tgt)
1525{
1526 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1527 struct uvcg_color_matching *color_matching_desc;
1528 struct config_item *streaming;
1529 struct uvcg_format *fmt;
1530
1531 mutex_lock(su_mutex);
1532
1533 color_matching_desc = to_uvcg_color_matching(to_config_group(tgt));
1534 color_matching_desc->refcnt--;
1535
1536 streaming = src->ci_parent->ci_parent;
1537 color_matching_desc = uvcg_format_get_default_color_match(streaming);
1538
1539 fmt = to_uvcg_format(src);
1540 fmt->color_matching = color_matching_desc;
1541 color_matching_desc->refcnt++;
1542
1543 mutex_unlock(su_mutex);
1544}
1545
1546static struct configfs_item_operations uvcg_format_item_operations = {
1547 .release = uvcg_config_item_release,
1548 .allow_link = uvcg_format_allow_link,
1549 .drop_link = uvcg_format_drop_link,
1550};
1551
1552static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
1553{
1554 struct f_uvc_opts *opts;
1555 struct config_item *opts_item;
1556 struct mutex *su_mutex = &f->group.cg_subsys->su_mutex;
1557 int result, i;
1558 char *pg = page;
1559
1560 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1561
1562 opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent;
1563 opts = to_f_uvc_opts(opts_item);
1564
1565 mutex_lock(&opts->lock);
1566 result = sprintf(pg, "0x");
1567 pg += result;
1568 for (i = 0; i < UVCG_STREAMING_CONTROL_SIZE; ++i) {
1569 result += sprintf(pg, "%x\n", f->bmaControls[i]);
1570 pg = page + result;
1571 }
1572 mutex_unlock(&opts->lock);
1573
1574 mutex_unlock(su_mutex);
1575 return result;
1576}
1577
1578static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch,
1579 const char *page, size_t len)
1580{
1581 struct f_uvc_opts *opts;
1582 struct config_item *opts_item;
1583 struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex;
1584 int ret = -EINVAL;
1585
1586 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1587
1588 opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent;
1589 opts = to_f_uvc_opts(opts_item);
1590
1591 mutex_lock(&opts->lock);
1592 if (ch->linked || opts->refcnt) {
1593 ret = -EBUSY;
1594 goto end;
1595 }
1596
1597 if (len < 4 || *page != '0' ||
1598 (*(page + 1) != 'x' && *(page + 1) != 'X'))
1599 goto end;
1600 ret = hex2bin(ch->bmaControls, page + 2, 1);
1601 if (ret < 0)
1602 goto end;
1603 ret = len;
1604end:
1605 mutex_unlock(&opts->lock);
1606 mutex_unlock(su_mutex);
1607 return ret;
1608}
1609
1610/* -----------------------------------------------------------------------------
1611 * streaming/header/<NAME>
1612 * streaming/header
1613 */
1614
1615static void uvcg_format_set_indices(struct config_group *fmt);
1616
1617static int uvcg_streaming_header_allow_link(struct config_item *src,
1618 struct config_item *target)
1619{
1620 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1621 struct config_item *opts_item;
1622 struct f_uvc_opts *opts;
1623 struct uvcg_streaming_header *src_hdr;
1624 struct uvcg_format *target_fmt = NULL;
1625 struct uvcg_format_ptr *format_ptr;
1626 int i, ret = -EINVAL;
1627
1628 src_hdr = to_uvcg_streaming_header(src);
1629 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1630
1631 opts_item = src->ci_parent->ci_parent->ci_parent;
1632 opts = to_f_uvc_opts(opts_item);
1633
1634 mutex_lock(&opts->lock);
1635
1636 if (src_hdr->linked) {
1637 ret = -EBUSY;
1638 goto out;
1639 }
1640
1641 /*
1642 * Linking is only allowed to direct children of the format nodes
1643 * (streaming/uncompressed or streaming/mjpeg nodes). First check that
1644 * the grand-parent of the target matches the grand-parent of the source
1645 * (the streaming node), and then verify that the target parent is a
1646 * format node.
1647 */
1648 if (src->ci_parent->ci_parent != target->ci_parent->ci_parent)
1649 goto out;
1650
1651 for (i = 0; i < ARRAY_SIZE(uvcg_format_names); ++i) {
1652 if (!strcmp(target->ci_parent->ci_name, uvcg_format_names[i]))
1653 break;
1654 }
1655
1656 if (i == ARRAY_SIZE(uvcg_format_names))
1657 goto out;
1658
1659 target_fmt = container_of(to_config_group(target), struct uvcg_format,
1660 group);
1661
1662 uvcg_format_set_indices(to_config_group(target));
1663
1664 format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
1665 if (!format_ptr) {
1666 ret = -ENOMEM;
1667 goto out;
1668 }
1669 ret = 0;
1670 format_ptr->fmt = target_fmt;
1671 list_add_tail(&format_ptr->entry, &src_hdr->formats);
1672 ++src_hdr->num_fmt;
1673 ++target_fmt->linked;
1674
1675out:
1676 mutex_unlock(&opts->lock);
1677 mutex_unlock(su_mutex);
1678 return ret;
1679}
1680
1681static void uvcg_streaming_header_drop_link(struct config_item *src,
1682 struct config_item *target)
1683{
1684 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
1685 struct config_item *opts_item;
1686 struct f_uvc_opts *opts;
1687 struct uvcg_streaming_header *src_hdr;
1688 struct uvcg_format *target_fmt = NULL;
1689 struct uvcg_format_ptr *format_ptr, *tmp;
1690
1691 src_hdr = to_uvcg_streaming_header(src);
1692 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1693
1694 opts_item = src->ci_parent->ci_parent->ci_parent;
1695 opts = to_f_uvc_opts(opts_item);
1696
1697 mutex_lock(&opts->lock);
1698 target_fmt = container_of(to_config_group(target), struct uvcg_format,
1699 group);
1700
1701 list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
1702 if (format_ptr->fmt == target_fmt) {
1703 list_del(&format_ptr->entry);
1704 kfree(format_ptr);
1705 --src_hdr->num_fmt;
1706 break;
1707 }
1708
1709 --target_fmt->linked;
1710
1711 mutex_unlock(&opts->lock);
1712 mutex_unlock(su_mutex);
1713}
1714
1715static struct configfs_item_operations uvcg_streaming_header_item_ops = {
1716 .release = uvcg_config_item_release,
1717 .allow_link = uvcg_streaming_header_allow_link,
1718 .drop_link = uvcg_streaming_header_drop_link,
1719};
1720
1721#define UVCG_STREAMING_HEADER_ATTR(cname, aname, bits) \
1722static ssize_t uvcg_streaming_header_##cname##_show( \
1723 struct config_item *item, char *page) \
1724{ \
1725 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
1726 struct f_uvc_opts *opts; \
1727 struct config_item *opts_item; \
1728 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\
1729 int result; \
1730 \
1731 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1732 \
1733 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \
1734 opts = to_f_uvc_opts(opts_item); \
1735 \
1736 mutex_lock(&opts->lock); \
1737 result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\
1738 mutex_unlock(&opts->lock); \
1739 \
1740 mutex_unlock(su_mutex); \
1741 return result; \
1742} \
1743 \
1744UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
1745
1746UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, 8);
1747UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, 8);
1748UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, 8);
1749UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, 8);
1750UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, 8);
1751
1752#undef UVCG_STREAMING_HEADER_ATTR
1753
1754static struct configfs_attribute *uvcg_streaming_header_attrs[] = {
1755 &uvcg_streaming_header_attr_bm_info,
1756 &uvcg_streaming_header_attr_b_terminal_link,
1757 &uvcg_streaming_header_attr_b_still_capture_method,
1758 &uvcg_streaming_header_attr_b_trigger_support,
1759 &uvcg_streaming_header_attr_b_trigger_usage,
1760 NULL,
1761};
1762
1763static const struct config_item_type uvcg_streaming_header_type = {
1764 .ct_item_ops = &uvcg_streaming_header_item_ops,
1765 .ct_attrs = uvcg_streaming_header_attrs,
1766 .ct_owner = THIS_MODULE,
1767};
1768
1769static struct config_item
1770*uvcg_streaming_header_make(struct config_group *group, const char *name)
1771{
1772 struct uvcg_streaming_header *h;
1773
1774 h = kzalloc(sizeof(*h), GFP_KERNEL);
1775 if (!h)
1776 return ERR_PTR(-ENOMEM);
1777
1778 INIT_LIST_HEAD(&h->formats);
1779 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
1780 h->desc.bDescriptorSubType = UVC_VS_INPUT_HEADER;
1781 h->desc.bTerminalLink = 3;
1782 h->desc.bControlSize = UVCG_STREAMING_CONTROL_SIZE;
1783
1784 config_item_init_type_name(&h->item, name, &uvcg_streaming_header_type);
1785
1786 return &h->item;
1787}
1788
1789static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
1790 .make_item = uvcg_streaming_header_make,
1791};
1792
1793static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = {
1794 .type = {
1795 .ct_item_ops = &uvcg_config_item_ops,
1796 .ct_group_ops = &uvcg_streaming_header_grp_ops,
1797 .ct_owner = THIS_MODULE,
1798 },
1799 .name = "header",
1800};
1801
1802/* -----------------------------------------------------------------------------
1803 * streaming/<mode>/<format>/<NAME>
1804 */
1805
1806#define UVCG_FRAME_ATTR(cname, aname, bits) \
1807static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
1808{ \
1809 struct uvcg_frame *f = to_uvcg_frame(item); \
1810 struct f_uvc_opts *opts; \
1811 struct config_item *opts_item; \
1812 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1813 int result; \
1814 \
1815 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1816 \
1817 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1818 opts = to_f_uvc_opts(opts_item); \
1819 \
1820 mutex_lock(&opts->lock); \
1821 result = sprintf(page, "%u\n", f->frame.cname); \
1822 mutex_unlock(&opts->lock); \
1823 \
1824 mutex_unlock(su_mutex); \
1825 return result; \
1826} \
1827 \
1828static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
1829 const char *page, size_t len)\
1830{ \
1831 struct uvcg_frame *f = to_uvcg_frame(item); \
1832 struct f_uvc_opts *opts; \
1833 struct config_item *opts_item; \
1834 struct uvcg_format *fmt; \
1835 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
1836 typeof(f->frame.cname) num; \
1837 int ret; \
1838 \
1839 ret = kstrtou##bits(page, 0, &num); \
1840 if (ret) \
1841 return ret; \
1842 \
1843 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
1844 \
1845 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
1846 opts = to_f_uvc_opts(opts_item); \
1847 fmt = to_uvcg_format(f->item.ci_parent); \
1848 \
1849 mutex_lock(&opts->lock); \
1850 if (fmt->linked || opts->refcnt) { \
1851 ret = -EBUSY; \
1852 goto end; \
1853 } \
1854 \
1855 f->frame.cname = num; \
1856 ret = len; \
1857end: \
1858 mutex_unlock(&opts->lock); \
1859 mutex_unlock(su_mutex); \
1860 return ret; \
1861} \
1862 \
1863UVC_ATTR(uvcg_frame_, cname, aname);
1864
1865static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
1866 char *page)
1867{
1868 struct uvcg_frame *f = to_uvcg_frame(item);
1869 struct uvcg_format *fmt;
1870 struct f_uvc_opts *opts;
1871 struct config_item *opts_item;
1872 struct config_item *fmt_item;
1873 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;
1874 int result;
1875
1876 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1877
1878 fmt_item = f->item.ci_parent;
1879 fmt = to_uvcg_format(fmt_item);
1880
1881 if (!fmt->linked) {
1882 result = -EBUSY;
1883 goto out;
1884 }
1885
1886 opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
1887 opts = to_f_uvc_opts(opts_item);
1888
1889 mutex_lock(&opts->lock);
1890 result = sprintf(page, "%u\n", f->frame.b_frame_index);
1891 mutex_unlock(&opts->lock);
1892
1893out:
1894 mutex_unlock(su_mutex);
1895 return result;
1896}
1897
1898UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
1899
1900UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8);
1901UVCG_FRAME_ATTR(w_width, wWidth, 16);
1902UVCG_FRAME_ATTR(w_height, wHeight, 16);
1903UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
1904UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
1905UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
1906UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
1907
1908#undef UVCG_FRAME_ATTR
1909
1910static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
1911 char *page)
1912{
1913 struct uvcg_frame *frm = to_uvcg_frame(item);
1914 struct f_uvc_opts *opts;
1915 struct config_item *opts_item;
1916 struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
1917 int result, i;
1918 char *pg = page;
1919
1920 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1921
1922 opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
1923 opts = to_f_uvc_opts(opts_item);
1924
1925 mutex_lock(&opts->lock);
1926 for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
1927 result += sprintf(pg, "%u\n", frm->dw_frame_interval[i]);
1928 pg = page + result;
1929 }
1930 mutex_unlock(&opts->lock);
1931
1932 mutex_unlock(su_mutex);
1933 return result;
1934}
1935
1936static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
1937 const char *page, size_t len)
1938{
1939 struct uvcg_frame *ch = to_uvcg_frame(item);
1940 struct f_uvc_opts *opts;
1941 struct config_item *opts_item;
1942 struct uvcg_format *fmt;
1943 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
1944 int ret = 0, n = 0;
1945 u32 *frm_intrv, *tmp;
1946
1947 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
1948
1949 opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
1950 opts = to_f_uvc_opts(opts_item);
1951 fmt = to_uvcg_format(ch->item.ci_parent);
1952
1953 mutex_lock(&opts->lock);
1954 if (fmt->linked || opts->refcnt) {
1955 ret = -EBUSY;
1956 goto end;
1957 }
1958
1959 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, sizeof(u32));
1960 if (ret)
1961 goto end;
1962
1963 tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL);
1964 if (!frm_intrv) {
1965 ret = -ENOMEM;
1966 goto end;
1967 }
1968
1969 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp, sizeof(u32));
1970 if (ret) {
1971 kfree(frm_intrv);
1972 goto end;
1973 }
1974
1975 kfree(ch->dw_frame_interval);
1976 ch->dw_frame_interval = frm_intrv;
1977 ch->frame.b_frame_interval_type = n;
1978 sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
1979 uvcg_config_compare_u32, NULL);
1980 ret = len;
1981
1982end:
1983 mutex_unlock(&opts->lock);
1984 mutex_unlock(su_mutex);
1985 return ret;
1986}
1987
1988UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
1989
1990static struct configfs_attribute *uvcg_frame_attrs[] = {
1991 &uvcg_frame_attr_b_frame_index,
1992 &uvcg_frame_attr_bm_capabilities,
1993 &uvcg_frame_attr_w_width,
1994 &uvcg_frame_attr_w_height,
1995 &uvcg_frame_attr_dw_min_bit_rate,
1996 &uvcg_frame_attr_dw_max_bit_rate,
1997 &uvcg_frame_attr_dw_max_video_frame_buffer_size,
1998 &uvcg_frame_attr_dw_default_frame_interval,
1999 &uvcg_frame_attr_dw_frame_interval,
2000 NULL,
2001};
2002
2003static const struct config_item_type uvcg_frame_type = {
2004 .ct_item_ops = &uvcg_config_item_ops,
2005 .ct_attrs = uvcg_frame_attrs,
2006 .ct_owner = THIS_MODULE,
2007};
2008
2009static struct config_item *uvcg_frame_make(struct config_group *group,
2010 const char *name)
2011{
2012 struct uvcg_frame *h;
2013 struct uvcg_format *fmt;
2014 struct f_uvc_opts *opts;
2015 struct config_item *opts_item;
2016 struct uvcg_frame_ptr *frame_ptr;
2017
2018 h = kzalloc(sizeof(*h), GFP_KERNEL);
2019 if (!h)
2020 return ERR_PTR(-ENOMEM);
2021
2022 h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
2023 h->frame.b_frame_index = 1;
2024 h->frame.w_width = 640;
2025 h->frame.w_height = 360;
2026 h->frame.dw_min_bit_rate = 18432000;
2027 h->frame.dw_max_bit_rate = 55296000;
2028 h->frame.dw_max_video_frame_buffer_size = 460800;
2029 h->frame.dw_default_frame_interval = 666666;
2030
2031 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
2032 opts = to_f_uvc_opts(opts_item);
2033
2034 mutex_lock(&opts->lock);
2035 fmt = to_uvcg_format(&group->cg_item);
2036 if (fmt->type == UVCG_UNCOMPRESSED) {
2037 h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED;
2038 h->fmt_type = UVCG_UNCOMPRESSED;
2039 } else if (fmt->type == UVCG_MJPEG) {
2040 h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
2041 h->fmt_type = UVCG_MJPEG;
2042 } else {
2043 mutex_unlock(&opts->lock);
2044 kfree(h);
2045 return ERR_PTR(-EINVAL);
2046 }
2047
2048 frame_ptr = kzalloc(sizeof(*frame_ptr), GFP_KERNEL);
2049 if (!frame_ptr) {
2050 mutex_unlock(&opts->lock);
2051 kfree(h);
2052 return ERR_PTR(-ENOMEM);
2053 }
2054
2055 frame_ptr->frm = h;
2056 list_add_tail(&frame_ptr->entry, &fmt->frames);
2057 ++fmt->num_frames;
2058 mutex_unlock(&opts->lock);
2059
2060 config_item_init_type_name(&h->item, name, &uvcg_frame_type);
2061
2062 return &h->item;
2063}
2064
2065static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
2066{
2067 struct uvcg_format *fmt;
2068 struct f_uvc_opts *opts;
2069 struct config_item *opts_item;
2070 struct uvcg_frame *target_frm = NULL;
2071 struct uvcg_frame_ptr *frame_ptr, *tmp;
2072
2073 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
2074 opts = to_f_uvc_opts(opts_item);
2075
2076 mutex_lock(&opts->lock);
2077 target_frm = container_of(item, struct uvcg_frame, item);
2078 fmt = to_uvcg_format(&group->cg_item);
2079
2080 list_for_each_entry_safe(frame_ptr, tmp, &fmt->frames, entry)
2081 if (frame_ptr->frm == target_frm) {
2082 list_del(&frame_ptr->entry);
2083 kfree(frame_ptr);
2084 --fmt->num_frames;
2085 break;
2086 }
2087 mutex_unlock(&opts->lock);
2088
2089 config_item_put(item);
2090}
2091
2092static void uvcg_format_set_indices(struct config_group *fmt)
2093{
2094 struct config_item *ci;
2095 unsigned int i = 1;
2096
2097 list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
2098 struct uvcg_frame *frm;
2099
2100 if (ci->ci_type != &uvcg_frame_type)
2101 continue;
2102
2103 frm = to_uvcg_frame(ci);
2104 frm->frame.b_frame_index = i++;
2105 }
2106}
2107
2108/* -----------------------------------------------------------------------------
2109 * streaming/uncompressed/<NAME>
2110 */
2111
2112static struct configfs_group_operations uvcg_uncompressed_group_ops = {
2113 .make_item = uvcg_frame_make,
2114 .drop_item = uvcg_frame_drop,
2115};
2116
2117static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item,
2118 char *page)
2119{
2120 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
2121 struct f_uvc_opts *opts;
2122 struct config_item *opts_item;
2123 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
2124
2125 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2126
2127 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
2128 opts = to_f_uvc_opts(opts_item);
2129
2130 mutex_lock(&opts->lock);
2131 memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
2132 mutex_unlock(&opts->lock);
2133
2134 mutex_unlock(su_mutex);
2135
2136 return sizeof(ch->desc.guidFormat);
2137}
2138
2139static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item,
2140 const char *page, size_t len)
2141{
2142 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item);
2143 struct f_uvc_opts *opts;
2144 struct config_item *opts_item;
2145 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
2146 int ret;
2147
2148 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2149
2150 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
2151 opts = to_f_uvc_opts(opts_item);
2152
2153 mutex_lock(&opts->lock);
2154 if (ch->fmt.linked || opts->refcnt) {
2155 ret = -EBUSY;
2156 goto end;
2157 }
2158
2159 memcpy(ch->desc.guidFormat, page,
2160 min(sizeof(ch->desc.guidFormat), len));
2161 ret = sizeof(ch->desc.guidFormat);
2162
2163end:
2164 mutex_unlock(&opts->lock);
2165 mutex_unlock(su_mutex);
2166 return ret;
2167}
2168
2169UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
2170
2171#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, bits) \
2172static ssize_t uvcg_uncompressed_##cname##_show( \
2173 struct config_item *item, char *page) \
2174{ \
2175 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
2176 struct f_uvc_opts *opts; \
2177 struct config_item *opts_item; \
2178 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
2179 int result; \
2180 \
2181 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2182 \
2183 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
2184 opts = to_f_uvc_opts(opts_item); \
2185 \
2186 mutex_lock(&opts->lock); \
2187 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
2188 mutex_unlock(&opts->lock); \
2189 \
2190 mutex_unlock(su_mutex); \
2191 return result; \
2192} \
2193 \
2194UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
2195
2196#define UVCG_UNCOMPRESSED_ATTR(cname, aname, bits) \
2197static ssize_t uvcg_uncompressed_##cname##_show( \
2198 struct config_item *item, char *page) \
2199{ \
2200 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
2201 struct f_uvc_opts *opts; \
2202 struct config_item *opts_item; \
2203 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
2204 int result; \
2205 \
2206 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2207 \
2208 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
2209 opts = to_f_uvc_opts(opts_item); \
2210 \
2211 mutex_lock(&opts->lock); \
2212 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
2213 mutex_unlock(&opts->lock); \
2214 \
2215 mutex_unlock(su_mutex); \
2216 return result; \
2217} \
2218 \
2219static ssize_t \
2220uvcg_uncompressed_##cname##_store(struct config_item *item, \
2221 const char *page, size_t len) \
2222{ \
2223 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \
2224 struct f_uvc_opts *opts; \
2225 struct config_item *opts_item; \
2226 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
2227 int ret; \
2228 u8 num; \
2229 \
2230 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2231 \
2232 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
2233 opts = to_f_uvc_opts(opts_item); \
2234 \
2235 mutex_lock(&opts->lock); \
2236 if (u->fmt.linked || opts->refcnt) { \
2237 ret = -EBUSY; \
2238 goto end; \
2239 } \
2240 \
2241 ret = kstrtou8(page, 0, &num); \
2242 if (ret) \
2243 goto end; \
2244 \
2245 /* index values in uvc are never 0 */ \
2246 if (!num) { \
2247 ret = -EINVAL; \
2248 goto end; \
2249 } \
2250 \
2251 u->desc.aname = num; \
2252 ret = len; \
2253end: \
2254 mutex_unlock(&opts->lock); \
2255 mutex_unlock(su_mutex); \
2256 return ret; \
2257} \
2258 \
2259UVC_ATTR(uvcg_uncompressed_, cname, aname);
2260
2261UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, 8);
2262UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8);
2263UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
2264UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
2265UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
2266UVCG_UNCOMPRESSED_ATTR_RO(bm_interlace_flags, bmInterlaceFlags, 8);
2267
2268#undef UVCG_UNCOMPRESSED_ATTR
2269#undef UVCG_UNCOMPRESSED_ATTR_RO
2270
2271static inline ssize_t
2272uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page)
2273{
2274 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
2275 return uvcg_format_bma_controls_show(&unc->fmt, page);
2276}
2277
2278static inline ssize_t
2279uvcg_uncompressed_bma_controls_store(struct config_item *item,
2280 const char *page, size_t len)
2281{
2282 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item);
2283 return uvcg_format_bma_controls_store(&unc->fmt, page, len);
2284}
2285
2286UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
2287
2288static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
2289 &uvcg_uncompressed_attr_b_format_index,
2290 &uvcg_uncompressed_attr_guid_format,
2291 &uvcg_uncompressed_attr_b_bits_per_pixel,
2292 &uvcg_uncompressed_attr_b_default_frame_index,
2293 &uvcg_uncompressed_attr_b_aspect_ratio_x,
2294 &uvcg_uncompressed_attr_b_aspect_ratio_y,
2295 &uvcg_uncompressed_attr_bm_interlace_flags,
2296 &uvcg_uncompressed_attr_bma_controls,
2297 NULL,
2298};
2299
2300static const struct config_item_type uvcg_uncompressed_type = {
2301 .ct_item_ops = &uvcg_format_item_operations,
2302 .ct_group_ops = &uvcg_uncompressed_group_ops,
2303 .ct_attrs = uvcg_uncompressed_attrs,
2304 .ct_owner = THIS_MODULE,
2305};
2306
2307static struct config_group *uvcg_uncompressed_make(struct config_group *group,
2308 const char *name)
2309{
2310 static char guid[] = {
2311 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
2312 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
2313 };
2314 struct uvcg_color_matching *color_match;
2315 struct config_item *streaming;
2316 struct uvcg_uncompressed *h;
2317
2318 streaming = group->cg_item.ci_parent;
2319 color_match = uvcg_format_get_default_color_match(streaming);
2320 if (!color_match)
2321 return ERR_PTR(-EINVAL);
2322
2323 h = kzalloc(sizeof(*h), GFP_KERNEL);
2324 if (!h)
2325 return ERR_PTR(-ENOMEM);
2326
2327 h->desc.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE;
2328 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
2329 h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED;
2330 memcpy(h->desc.guidFormat, guid, sizeof(guid));
2331 h->desc.bBitsPerPixel = 16;
2332 h->desc.bDefaultFrameIndex = 1;
2333 h->desc.bAspectRatioX = 0;
2334 h->desc.bAspectRatioY = 0;
2335 h->desc.bmInterlaceFlags = 0;
2336 h->desc.bCopyProtect = 0;
2337
2338 INIT_LIST_HEAD(&h->fmt.frames);
2339 h->fmt.type = UVCG_UNCOMPRESSED;
2340 h->fmt.color_matching = color_match;
2341 color_match->refcnt++;
2342 config_group_init_type_name(&h->fmt.group, name,
2343 &uvcg_uncompressed_type);
2344
2345 return &h->fmt.group;
2346}
2347
2348static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
2349 .make_group = uvcg_uncompressed_make,
2350};
2351
2352static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = {
2353 .type = {
2354 .ct_item_ops = &uvcg_config_item_ops,
2355 .ct_group_ops = &uvcg_uncompressed_grp_ops,
2356 .ct_owner = THIS_MODULE,
2357 },
2358 .name = "uncompressed",
2359};
2360
2361/* -----------------------------------------------------------------------------
2362 * streaming/mjpeg/<NAME>
2363 */
2364
2365static struct configfs_group_operations uvcg_mjpeg_group_ops = {
2366 .make_item = uvcg_frame_make,
2367 .drop_item = uvcg_frame_drop,
2368};
2369
2370#define UVCG_MJPEG_ATTR_RO(cname, aname, bits) \
2371static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
2372{ \
2373 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
2374 struct f_uvc_opts *opts; \
2375 struct config_item *opts_item; \
2376 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
2377 int result; \
2378 \
2379 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2380 \
2381 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
2382 opts = to_f_uvc_opts(opts_item); \
2383 \
2384 mutex_lock(&opts->lock); \
2385 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
2386 mutex_unlock(&opts->lock); \
2387 \
2388 mutex_unlock(su_mutex); \
2389 return result; \
2390} \
2391 \
2392UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
2393
2394#define UVCG_MJPEG_ATTR(cname, aname, bits) \
2395static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
2396{ \
2397 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
2398 struct f_uvc_opts *opts; \
2399 struct config_item *opts_item; \
2400 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
2401 int result; \
2402 \
2403 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2404 \
2405 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
2406 opts = to_f_uvc_opts(opts_item); \
2407 \
2408 mutex_lock(&opts->lock); \
2409 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
2410 mutex_unlock(&opts->lock); \
2411 \
2412 mutex_unlock(su_mutex); \
2413 return result; \
2414} \
2415 \
2416static ssize_t \
2417uvcg_mjpeg_##cname##_store(struct config_item *item, \
2418 const char *page, size_t len) \
2419{ \
2420 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
2421 struct f_uvc_opts *opts; \
2422 struct config_item *opts_item; \
2423 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
2424 int ret; \
2425 u8 num; \
2426 \
2427 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2428 \
2429 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
2430 opts = to_f_uvc_opts(opts_item); \
2431 \
2432 mutex_lock(&opts->lock); \
2433 if (u->fmt.linked || opts->refcnt) { \
2434 ret = -EBUSY; \
2435 goto end; \
2436 } \
2437 \
2438 ret = kstrtou8(page, 0, &num); \
2439 if (ret) \
2440 goto end; \
2441 \
2442 /* index values in uvc are never 0 */ \
2443 if (!num) { \
2444 ret = -EINVAL; \
2445 goto end; \
2446 } \
2447 \
2448 u->desc.aname = num; \
2449 ret = len; \
2450end: \
2451 mutex_unlock(&opts->lock); \
2452 mutex_unlock(su_mutex); \
2453 return ret; \
2454} \
2455 \
2456UVC_ATTR(uvcg_mjpeg_, cname, aname)
2457
2458UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, 8);
2459UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
2460UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8);
2461UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
2462UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
2463UVCG_MJPEG_ATTR_RO(bm_interlace_flags, bmInterlaceFlags, 8);
2464
2465#undef UVCG_MJPEG_ATTR
2466#undef UVCG_MJPEG_ATTR_RO
2467
2468static inline ssize_t
2469uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page)
2470{
2471 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
2472 return uvcg_format_bma_controls_show(&u->fmt, page);
2473}
2474
2475static inline ssize_t
2476uvcg_mjpeg_bma_controls_store(struct config_item *item,
2477 const char *page, size_t len)
2478{
2479 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item);
2480 return uvcg_format_bma_controls_store(&u->fmt, page, len);
2481}
2482
2483UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
2484
2485static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
2486 &uvcg_mjpeg_attr_b_format_index,
2487 &uvcg_mjpeg_attr_b_default_frame_index,
2488 &uvcg_mjpeg_attr_bm_flags,
2489 &uvcg_mjpeg_attr_b_aspect_ratio_x,
2490 &uvcg_mjpeg_attr_b_aspect_ratio_y,
2491 &uvcg_mjpeg_attr_bm_interlace_flags,
2492 &uvcg_mjpeg_attr_bma_controls,
2493 NULL,
2494};
2495
2496static const struct config_item_type uvcg_mjpeg_type = {
2497 .ct_item_ops = &uvcg_format_item_operations,
2498 .ct_group_ops = &uvcg_mjpeg_group_ops,
2499 .ct_attrs = uvcg_mjpeg_attrs,
2500 .ct_owner = THIS_MODULE,
2501};
2502
2503static struct config_group *uvcg_mjpeg_make(struct config_group *group,
2504 const char *name)
2505{
2506 struct uvcg_color_matching *color_match;
2507 struct config_item *streaming;
2508 struct uvcg_mjpeg *h;
2509
2510 streaming = group->cg_item.ci_parent;
2511 color_match = uvcg_format_get_default_color_match(streaming);
2512 if (!color_match)
2513 return ERR_PTR(-EINVAL);
2514
2515 h = kzalloc(sizeof(*h), GFP_KERNEL);
2516 if (!h)
2517 return ERR_PTR(-ENOMEM);
2518
2519 h->desc.bLength = UVC_DT_FORMAT_MJPEG_SIZE;
2520 h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
2521 h->desc.bDescriptorSubType = UVC_VS_FORMAT_MJPEG;
2522 h->desc.bDefaultFrameIndex = 1;
2523 h->desc.bAspectRatioX = 0;
2524 h->desc.bAspectRatioY = 0;
2525 h->desc.bmInterlaceFlags = 0;
2526 h->desc.bCopyProtect = 0;
2527
2528 INIT_LIST_HEAD(&h->fmt.frames);
2529 h->fmt.type = UVCG_MJPEG;
2530 h->fmt.color_matching = color_match;
2531 color_match->refcnt++;
2532 config_group_init_type_name(&h->fmt.group, name,
2533 &uvcg_mjpeg_type);
2534
2535 return &h->fmt.group;
2536}
2537
2538static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
2539 .make_group = uvcg_mjpeg_make,
2540};
2541
2542static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
2543 .type = {
2544 .ct_item_ops = &uvcg_config_item_ops,
2545 .ct_group_ops = &uvcg_mjpeg_grp_ops,
2546 .ct_owner = THIS_MODULE,
2547 },
2548 .name = "mjpeg",
2549};
2550
2551/* -----------------------------------------------------------------------------
2552 * streaming/color_matching/default
2553 */
2554
2555#define UVCG_COLOR_MATCHING_ATTR(cname, aname, bits) \
2556static ssize_t uvcg_color_matching_##cname##_show( \
2557 struct config_item *item, char *page) \
2558{ \
2559 struct config_group *group = to_config_group(item); \
2560 struct uvcg_color_matching *color_match = \
2561 to_uvcg_color_matching(group); \
2562 struct f_uvc_opts *opts; \
2563 struct config_item *opts_item; \
2564 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
2565 int result; \
2566 \
2567 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2568 \
2569 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
2570 opts = to_f_uvc_opts(opts_item); \
2571 \
2572 mutex_lock(&opts->lock); \
2573 result = sprintf(page, "%u\n", \
2574 le##bits##_to_cpu(color_match->desc.aname)); \
2575 mutex_unlock(&opts->lock); \
2576 \
2577 mutex_unlock(su_mutex); \
2578 return result; \
2579} \
2580 \
2581static ssize_t uvcg_color_matching_##cname##_store( \
2582 struct config_item *item, const char *page, size_t len) \
2583{ \
2584 struct config_group *group = to_config_group(item); \
2585 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
2586 struct uvcg_color_matching *color_match = \
2587 to_uvcg_color_matching(group); \
2588 struct f_uvc_opts *opts; \
2589 struct config_item *opts_item; \
2590 int ret; \
2591 u##bits num; \
2592 \
2593 ret = kstrtou##bits(page, 0, &num); \
2594 if (ret) \
2595 return ret; \
2596 \
2597 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
2598 \
2599 if (color_match->refcnt) { \
2600 ret = -EBUSY; \
2601 goto unlock_su; \
2602 } \
2603 \
2604 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
2605 opts = to_f_uvc_opts(opts_item); \
2606 \
2607 mutex_lock(&opts->lock); \
2608 \
2609 color_match->desc.aname = num; \
2610 ret = len; \
2611 \
2612 mutex_unlock(&opts->lock); \
2613unlock_su: \
2614 mutex_unlock(su_mutex); \
2615 \
2616 return ret; \
2617} \
2618UVC_ATTR(uvcg_color_matching_, cname, aname)
2619
2620UVCG_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 8);
2621UVCG_COLOR_MATCHING_ATTR(b_transfer_characteristics, bTransferCharacteristics, 8);
2622UVCG_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 8);
2623
2624#undef UVCG_COLOR_MATCHING_ATTR
2625
2626static struct configfs_attribute *uvcg_color_matching_attrs[] = {
2627 &uvcg_color_matching_attr_b_color_primaries,
2628 &uvcg_color_matching_attr_b_transfer_characteristics,
2629 &uvcg_color_matching_attr_b_matrix_coefficients,
2630 NULL,
2631};
2632
2633static void uvcg_color_matching_release(struct config_item *item)
2634{
2635 struct uvcg_color_matching *color_match =
2636 to_uvcg_color_matching(to_config_group(item));
2637
2638 kfree(color_match);
2639}
2640
2641static struct configfs_item_operations uvcg_color_matching_item_ops = {
2642 .release = uvcg_color_matching_release,
2643};
2644
2645static const struct config_item_type uvcg_color_matching_type = {
2646 .ct_item_ops = &uvcg_color_matching_item_ops,
2647 .ct_attrs = uvcg_color_matching_attrs,
2648 .ct_owner = THIS_MODULE,
2649};
2650
2651/* -----------------------------------------------------------------------------
2652 * streaming/color_matching
2653 */
2654
2655static struct config_group *uvcg_color_matching_make(struct config_group *group,
2656 const char *name)
2657{
2658 struct uvcg_color_matching *color_match;
2659
2660 color_match = kzalloc(sizeof(*color_match), GFP_KERNEL);
2661 if (!color_match)
2662 return ERR_PTR(-ENOMEM);
2663
2664 color_match->desc.bLength = UVC_DT_COLOR_MATCHING_SIZE;
2665 color_match->desc.bDescriptorType = USB_DT_CS_INTERFACE;
2666 color_match->desc.bDescriptorSubType = UVC_VS_COLORFORMAT;
2667
2668 config_group_init_type_name(&color_match->group, name,
2669 &uvcg_color_matching_type);
2670
2671 return &color_match->group;
2672}
2673
2674static struct configfs_group_operations uvcg_color_matching_grp_group_ops = {
2675 .make_group = uvcg_color_matching_make,
2676};
2677
2678static int uvcg_color_matching_create_children(struct config_group *parent)
2679{
2680 struct uvcg_color_matching *color_match;
2681
2682 color_match = kzalloc(sizeof(*color_match), GFP_KERNEL);
2683 if (!color_match)
2684 return -ENOMEM;
2685
2686 color_match->desc.bLength = UVC_DT_COLOR_MATCHING_SIZE;
2687 color_match->desc.bDescriptorType = USB_DT_CS_INTERFACE;
2688 color_match->desc.bDescriptorSubType = UVC_VS_COLORFORMAT;
2689 color_match->desc.bColorPrimaries = UVC_COLOR_PRIMARIES_BT_709_SRGB;
2690 color_match->desc.bTransferCharacteristics = UVC_TRANSFER_CHARACTERISTICS_BT_709;
2691 color_match->desc.bMatrixCoefficients = UVC_MATRIX_COEFFICIENTS_SMPTE_170M;
2692
2693 config_group_init_type_name(&color_match->group, "default",
2694 &uvcg_color_matching_type);
2695 configfs_add_default_group(&color_match->group, parent);
2696
2697 return 0;
2698}
2699
2700static const struct uvcg_config_group_type uvcg_color_matching_grp_type = {
2701 .type = {
2702 .ct_item_ops = &uvcg_config_item_ops,
2703 .ct_group_ops = &uvcg_color_matching_grp_group_ops,
2704 .ct_owner = THIS_MODULE,
2705 },
2706 .name = "color_matching",
2707 .create_children = uvcg_color_matching_create_children,
2708};
2709
2710/* -----------------------------------------------------------------------------
2711 * streaming/class/{fs|hs|ss}
2712 */
2713
2714struct uvcg_streaming_class_group {
2715 struct config_group group;
2716 const char *name;
2717};
2718
2719static inline struct uvc_descriptor_header
2720***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
2721{
2722 struct uvcg_streaming_class_group *group =
2723 container_of(i, struct uvcg_streaming_class_group,
2724 group.cg_item);
2725
2726 if (!strcmp(group->name, "fs"))
2727 return &o->uvc_fs_streaming_cls;
2728
2729 if (!strcmp(group->name, "hs"))
2730 return &o->uvc_hs_streaming_cls;
2731
2732 if (!strcmp(group->name, "ss"))
2733 return &o->uvc_ss_streaming_cls;
2734
2735 return NULL;
2736}
2737
2738enum uvcg_strm_type {
2739 UVCG_HEADER = 0,
2740 UVCG_FORMAT,
2741 UVCG_FRAME,
2742 UVCG_COLOR_MATCHING,
2743};
2744
2745/*
2746 * Iterate over a hierarchy of streaming descriptors' config items.
2747 * The items are created by the user with configfs.
2748 *
2749 * It "processes" the header pointed to by @priv1, then for each format
2750 * that follows the header "processes" the format itself and then for
2751 * each frame inside a format "processes" the frame.
2752 *
2753 * As a "processing" function the @fun is used.
2754 *
2755 * __uvcg_iter_strm_cls() is used in two context: first, to calculate
2756 * the amount of memory needed for an array of streaming descriptors
2757 * and second, to actually fill the array.
2758 *
2759 * @h: streaming header pointer
2760 * @priv2: an "inout" parameter (the caller might want to see the changes to it)
2761 * @priv3: an "inout" parameter (the caller might want to see the changes to it)
2762 * @fun: callback function for processing each level of the hierarchy
2763 */
2764static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
2765 void *priv2, void *priv3,
2766 int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type))
2767{
2768 struct uvcg_format_ptr *f;
2769 struct config_group *grp;
2770 struct config_item *item;
2771 struct uvcg_frame *frm;
2772 int ret, i, j;
2773
2774 if (!fun)
2775 return -EINVAL;
2776
2777 i = j = 0;
2778 ret = fun(h, priv2, priv3, 0, UVCG_HEADER);
2779 if (ret)
2780 return ret;
2781 list_for_each_entry(f, &h->formats, entry) {
2782 ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT);
2783 if (ret)
2784 return ret;
2785 grp = &f->fmt->group;
2786 list_for_each_entry(item, &grp->cg_children, ci_entry) {
2787 frm = to_uvcg_frame(item);
2788 ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
2789 if (ret)
2790 return ret;
2791 }
2792
2793 ret = fun(f->fmt->color_matching, priv2, priv3, 0,
2794 UVCG_COLOR_MATCHING);
2795 if (ret)
2796 return ret;
2797 }
2798
2799 return ret;
2800}
2801
2802/*
2803 * Count how many bytes are needed for an array of streaming descriptors.
2804 *
2805 * @priv1: pointer to a header, format or frame
2806 * @priv2: inout parameter, accumulated size of the array
2807 * @priv3: inout parameter, accumulated number of the array elements
2808 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls
2809 */
2810static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
2811 enum uvcg_strm_type type)
2812{
2813 size_t *size = priv2;
2814 size_t *count = priv3;
2815
2816 switch (type) {
2817 case UVCG_HEADER: {
2818 struct uvcg_streaming_header *h = priv1;
2819
2820 *size += sizeof(h->desc);
2821 /* bmaControls */
2822 *size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE;
2823 }
2824 break;
2825 case UVCG_FORMAT: {
2826 struct uvcg_format *fmt = priv1;
2827
2828 if (fmt->type == UVCG_UNCOMPRESSED) {
2829 struct uvcg_uncompressed *u =
2830 container_of(fmt, struct uvcg_uncompressed,
2831 fmt);
2832
2833 *size += sizeof(u->desc);
2834 } else if (fmt->type == UVCG_MJPEG) {
2835 struct uvcg_mjpeg *m =
2836 container_of(fmt, struct uvcg_mjpeg, fmt);
2837
2838 *size += sizeof(m->desc);
2839 } else {
2840 return -EINVAL;
2841 }
2842 }
2843 break;
2844 case UVCG_FRAME: {
2845 struct uvcg_frame *frm = priv1;
2846 int sz = sizeof(frm->dw_frame_interval);
2847
2848 *size += sizeof(frm->frame);
2849 *size += frm->frame.b_frame_interval_type * sz;
2850 }
2851 break;
2852 case UVCG_COLOR_MATCHING: {
2853 struct uvcg_color_matching *color_match = priv1;
2854
2855 *size += sizeof(color_match->desc);
2856 }
2857 break;
2858 }
2859
2860 ++*count;
2861
2862 return 0;
2863}
2864
2865/*
2866 * Fill an array of streaming descriptors.
2867 *
2868 * @priv1: pointer to a header, format or frame
2869 * @priv2: inout parameter, pointer into a block of memory
2870 * @priv3: inout parameter, pointer to a 2-dimensional array
2871 */
2872static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
2873 enum uvcg_strm_type type)
2874{
2875 void **dest = priv2;
2876 struct uvc_descriptor_header ***array = priv3;
2877 size_t sz;
2878
2879 **array = *dest;
2880 ++*array;
2881
2882 switch (type) {
2883 case UVCG_HEADER: {
2884 struct uvc_input_header_descriptor *ihdr = *dest;
2885 struct uvcg_streaming_header *h = priv1;
2886 struct uvcg_format_ptr *f;
2887
2888 memcpy(*dest, &h->desc, sizeof(h->desc));
2889 *dest += sizeof(h->desc);
2890 sz = UVCG_STREAMING_CONTROL_SIZE;
2891 list_for_each_entry(f, &h->formats, entry) {
2892 memcpy(*dest, f->fmt->bmaControls, sz);
2893 *dest += sz;
2894 }
2895 ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz;
2896 ihdr->bNumFormats = h->num_fmt;
2897 }
2898 break;
2899 case UVCG_FORMAT: {
2900 struct uvcg_format *fmt = priv1;
2901
2902 if (fmt->type == UVCG_UNCOMPRESSED) {
2903 struct uvcg_uncompressed *u =
2904 container_of(fmt, struct uvcg_uncompressed,
2905 fmt);
2906
2907 u->desc.bFormatIndex = n + 1;
2908 u->desc.bNumFrameDescriptors = fmt->num_frames;
2909 memcpy(*dest, &u->desc, sizeof(u->desc));
2910 *dest += sizeof(u->desc);
2911 } else if (fmt->type == UVCG_MJPEG) {
2912 struct uvcg_mjpeg *m =
2913 container_of(fmt, struct uvcg_mjpeg, fmt);
2914
2915 m->desc.bFormatIndex = n + 1;
2916 m->desc.bNumFrameDescriptors = fmt->num_frames;
2917 memcpy(*dest, &m->desc, sizeof(m->desc));
2918 *dest += sizeof(m->desc);
2919 } else {
2920 return -EINVAL;
2921 }
2922 }
2923 break;
2924 case UVCG_FRAME: {
2925 struct uvcg_frame *frm = priv1;
2926 struct uvc_descriptor_header *h = *dest;
2927
2928 sz = sizeof(frm->frame);
2929 memcpy(*dest, &frm->frame, sz);
2930 *dest += sz;
2931 sz = frm->frame.b_frame_interval_type *
2932 sizeof(*frm->dw_frame_interval);
2933 memcpy(*dest, frm->dw_frame_interval, sz);
2934 *dest += sz;
2935 if (frm->fmt_type == UVCG_UNCOMPRESSED)
2936 h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(
2937 frm->frame.b_frame_interval_type);
2938 else if (frm->fmt_type == UVCG_MJPEG)
2939 h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
2940 frm->frame.b_frame_interval_type);
2941 }
2942 break;
2943 case UVCG_COLOR_MATCHING: {
2944 struct uvcg_color_matching *color_match = priv1;
2945
2946 memcpy(*dest, &color_match->desc, sizeof(color_match->desc));
2947 *dest += sizeof(color_match->desc);
2948 }
2949 break;
2950 }
2951
2952 return 0;
2953}
2954
2955static int uvcg_streaming_class_allow_link(struct config_item *src,
2956 struct config_item *target)
2957{
2958 struct config_item *streaming, *header;
2959 struct f_uvc_opts *opts;
2960 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
2961 struct uvc_descriptor_header ***class_array, **cl_arr;
2962 struct uvcg_streaming_header *target_hdr;
2963 void *data, *data_save;
2964 size_t size = 0, count = 0;
2965 int ret = -EINVAL;
2966
2967 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
2968
2969 streaming = src->ci_parent->ci_parent;
2970 header = config_group_find_item(to_config_group(streaming), "header");
2971 if (!header || target->ci_parent != header)
2972 goto out;
2973
2974 opts = to_f_uvc_opts(streaming->ci_parent);
2975
2976 mutex_lock(&opts->lock);
2977
2978 class_array = __uvcg_get_stream_class_arr(src, opts);
2979 if (!class_array || *class_array || opts->refcnt) {
2980 ret = -EBUSY;
2981 goto unlock;
2982 }
2983
2984 target_hdr = to_uvcg_streaming_header(target);
2985 ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm);
2986 if (ret)
2987 goto unlock;
2988
2989 count += 1; /* NULL */
2990 *class_array = kcalloc(count, sizeof(void *), GFP_KERNEL);
2991 if (!*class_array) {
2992 ret = -ENOMEM;
2993 goto unlock;
2994 }
2995
2996 data = data_save = kzalloc(size, GFP_KERNEL);
2997 if (!data) {
2998 kfree(*class_array);
2999 *class_array = NULL;
3000 ret = -ENOMEM;
3001 goto unlock;
3002 }
3003 cl_arr = *class_array;
3004 ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr,
3005 __uvcg_fill_strm);
3006 if (ret) {
3007 kfree(*class_array);
3008 *class_array = NULL;
3009 /*
3010 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls()
3011 * might have advanced the "data", so use a backup copy
3012 */
3013 kfree(data_save);
3014 goto unlock;
3015 }
3016
3017 ++target_hdr->linked;
3018 ret = 0;
3019
3020unlock:
3021 mutex_unlock(&opts->lock);
3022out:
3023 config_item_put(header);
3024 mutex_unlock(su_mutex);
3025 return ret;
3026}
3027
3028static void uvcg_streaming_class_drop_link(struct config_item *src,
3029 struct config_item *target)
3030{
3031 struct config_item *streaming, *header;
3032 struct f_uvc_opts *opts;
3033 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
3034 struct uvc_descriptor_header ***class_array;
3035 struct uvcg_streaming_header *target_hdr;
3036
3037 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
3038
3039 streaming = src->ci_parent->ci_parent;
3040 header = config_group_find_item(to_config_group(streaming), "header");
3041 if (!header || target->ci_parent != header)
3042 goto out;
3043
3044 opts = to_f_uvc_opts(streaming->ci_parent);
3045
3046 mutex_lock(&opts->lock);
3047
3048 class_array = __uvcg_get_stream_class_arr(src, opts);
3049 if (!class_array || !*class_array)
3050 goto unlock;
3051
3052 if (opts->refcnt)
3053 goto unlock;
3054
3055 target_hdr = to_uvcg_streaming_header(target);
3056 --target_hdr->linked;
3057 kfree(**class_array);
3058 kfree(*class_array);
3059 *class_array = NULL;
3060
3061unlock:
3062 mutex_unlock(&opts->lock);
3063out:
3064 config_item_put(header);
3065 mutex_unlock(su_mutex);
3066}
3067
3068static struct configfs_item_operations uvcg_streaming_class_item_ops = {
3069 .release = uvcg_config_item_release,
3070 .allow_link = uvcg_streaming_class_allow_link,
3071 .drop_link = uvcg_streaming_class_drop_link,
3072};
3073
3074static const struct config_item_type uvcg_streaming_class_type = {
3075 .ct_item_ops = &uvcg_streaming_class_item_ops,
3076 .ct_owner = THIS_MODULE,
3077};
3078
3079/* -----------------------------------------------------------------------------
3080 * streaming/class
3081 */
3082
3083static int uvcg_streaming_class_create_children(struct config_group *parent)
3084{
3085 static const char * const names[] = { "fs", "hs", "ss" };
3086 unsigned int i;
3087
3088 for (i = 0; i < ARRAY_SIZE(names); ++i) {
3089 struct uvcg_streaming_class_group *group;
3090
3091 group = kzalloc(sizeof(*group), GFP_KERNEL);
3092 if (!group)
3093 return -ENOMEM;
3094
3095 group->name = names[i];
3096
3097 config_group_init_type_name(&group->group, group->name,
3098 &uvcg_streaming_class_type);
3099 configfs_add_default_group(&group->group, parent);
3100 }
3101
3102 return 0;
3103}
3104
3105static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = {
3106 .type = {
3107 .ct_item_ops = &uvcg_config_item_ops,
3108 .ct_owner = THIS_MODULE,
3109 },
3110 .name = "class",
3111 .create_children = uvcg_streaming_class_create_children,
3112};
3113
3114/* -----------------------------------------------------------------------------
3115 * streaming
3116 */
3117
3118static ssize_t uvcg_default_streaming_b_interface_number_show(
3119 struct config_item *item, char *page)
3120{
3121 struct config_group *group = to_config_group(item);
3122 struct mutex *su_mutex = &group->cg_subsys->su_mutex;
3123 struct config_item *opts_item;
3124 struct f_uvc_opts *opts;
3125 int result = 0;
3126
3127 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
3128
3129 opts_item = item->ci_parent;
3130 opts = to_f_uvc_opts(opts_item);
3131
3132 mutex_lock(&opts->lock);
3133 result += sprintf(page, "%u\n", opts->streaming_interface);
3134 mutex_unlock(&opts->lock);
3135
3136 mutex_unlock(su_mutex);
3137
3138 return result;
3139}
3140
3141UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber);
3142
3143static struct configfs_attribute *uvcg_default_streaming_attrs[] = {
3144 &uvcg_default_streaming_attr_b_interface_number,
3145 NULL,
3146};
3147
3148static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
3149 .type = {
3150 .ct_item_ops = &uvcg_config_item_ops,
3151 .ct_attrs = uvcg_default_streaming_attrs,
3152 .ct_owner = THIS_MODULE,
3153 },
3154 .name = "streaming",
3155 .children = (const struct uvcg_config_group_type*[]) {
3156 &uvcg_streaming_header_grp_type,
3157 &uvcg_uncompressed_grp_type,
3158 &uvcg_mjpeg_grp_type,
3159 &uvcg_color_matching_grp_type,
3160 &uvcg_streaming_class_grp_type,
3161 NULL,
3162 },
3163};
3164
3165/* -----------------------------------------------------------------------------
3166 * UVC function
3167 */
3168
3169static void uvc_func_item_release(struct config_item *item)
3170{
3171 struct f_uvc_opts *opts = to_f_uvc_opts(item);
3172
3173 uvcg_config_remove_children(to_config_group(item));
3174 usb_put_function_instance(&opts->func_inst);
3175}
3176
3177static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt)
3178{
3179 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
3180 struct gadget_string *string;
3181 struct config_item *strings;
3182 struct f_uvc_opts *opts;
3183 int ret = 0;
3184
3185 mutex_lock(su_mutex); /* for navigating configfs hierarchy */
3186
3187 /* Validate that the target is an entry in strings/<langid> */
3188 strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent),
3189 "strings");
3190 if (!strings || tgt->ci_parent->ci_parent != strings) {
3191 ret = -EINVAL;
3192 goto put_strings;
3193 }
3194
3195 string = to_gadget_string(tgt);
3196
3197 opts = to_f_uvc_opts(src);
3198 mutex_lock(&opts->lock);
3199
3200 if (!strcmp(tgt->ci_name, "iad_desc"))
3201 opts->iad_index = string->usb_string.id;
3202 else if (!strcmp(tgt->ci_name, "vs0_desc"))
3203 opts->vs0_index = string->usb_string.id;
3204 else if (!strcmp(tgt->ci_name, "vs1_desc"))
3205 opts->vs1_index = string->usb_string.id;
3206 else
3207 ret = -EINVAL;
3208
3209 mutex_unlock(&opts->lock);
3210
3211put_strings:
3212 config_item_put(strings);
3213 mutex_unlock(su_mutex);
3214
3215 return ret;
3216}
3217
3218static void uvc_func_drop_link(struct config_item *src, struct config_item *tgt)
3219{
3220 struct f_uvc_opts *opts;
3221
3222 opts = to_f_uvc_opts(src);
3223 mutex_lock(&opts->lock);
3224
3225 if (!strcmp(tgt->ci_name, "iad_desc"))
3226 opts->iad_index = 0;
3227 else if (!strcmp(tgt->ci_name, "vs0_desc"))
3228 opts->vs0_index = 0;
3229 else if (!strcmp(tgt->ci_name, "vs1_desc"))
3230 opts->vs1_index = 0;
3231
3232 mutex_unlock(&opts->lock);
3233}
3234
3235static struct configfs_item_operations uvc_func_item_ops = {
3236 .release = uvc_func_item_release,
3237 .allow_link = uvc_func_allow_link,
3238 .drop_link = uvc_func_drop_link,
3239};
3240
3241#define UVCG_OPTS_ATTR(cname, aname, limit) \
3242static ssize_t f_uvc_opts_##cname##_show( \
3243 struct config_item *item, char *page) \
3244{ \
3245 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
3246 int result; \
3247 \
3248 mutex_lock(&opts->lock); \
3249 result = sprintf(page, "%u\n", opts->cname); \
3250 mutex_unlock(&opts->lock); \
3251 \
3252 return result; \
3253} \
3254 \
3255static ssize_t \
3256f_uvc_opts_##cname##_store(struct config_item *item, \
3257 const char *page, size_t len) \
3258{ \
3259 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
3260 unsigned int num; \
3261 int ret; \
3262 \
3263 mutex_lock(&opts->lock); \
3264 if (opts->refcnt) { \
3265 ret = -EBUSY; \
3266 goto end; \
3267 } \
3268 \
3269 ret = kstrtouint(page, 0, &num); \
3270 if (ret) \
3271 goto end; \
3272 \
3273 if (num > limit) { \
3274 ret = -EINVAL; \
3275 goto end; \
3276 } \
3277 opts->cname = num; \
3278 ret = len; \
3279end: \
3280 mutex_unlock(&opts->lock); \
3281 return ret; \
3282} \
3283 \
3284UVC_ATTR(f_uvc_opts_, cname, cname)
3285
3286UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16);
3287UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072);
3288UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15);
3289
3290#undef UVCG_OPTS_ATTR
3291
3292#define UVCG_OPTS_STRING_ATTR(cname, aname) \
3293static ssize_t f_uvc_opts_string_##cname##_show(struct config_item *item,\
3294 char *page) \
3295{ \
3296 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
3297 int result; \
3298 \
3299 mutex_lock(&opts->lock); \
3300 result = snprintf(page, sizeof(opts->aname), "%s", opts->aname);\
3301 mutex_unlock(&opts->lock); \
3302 \
3303 return result; \
3304} \
3305 \
3306static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\
3307 const char *page, size_t len) \
3308{ \
3309 struct f_uvc_opts *opts = to_f_uvc_opts(item); \
3310 int size = min(sizeof(opts->aname), len + 1); \
3311 int ret = 0; \
3312 \
3313 mutex_lock(&opts->lock); \
3314 if (opts->refcnt) { \
3315 ret = -EBUSY; \
3316 goto end; \
3317 } \
3318 \
3319 ret = strscpy(opts->aname, page, size); \
3320 if (ret == -E2BIG) \
3321 ret = size - 1; \
3322 \
3323end: \
3324 mutex_unlock(&opts->lock); \
3325 return ret; \
3326} \
3327 \
3328UVC_ATTR(f_uvc_opts_string_, cname, aname)
3329
3330UVCG_OPTS_STRING_ATTR(function_name, function_name);
3331
3332#undef UVCG_OPTS_STRING_ATTR
3333
3334static struct configfs_attribute *uvc_attrs[] = {
3335 &f_uvc_opts_attr_streaming_interval,
3336 &f_uvc_opts_attr_streaming_maxpacket,
3337 &f_uvc_opts_attr_streaming_maxburst,
3338 &f_uvc_opts_string_attr_function_name,
3339 NULL,
3340};
3341
3342static const struct uvcg_config_group_type uvc_func_type = {
3343 .type = {
3344 .ct_item_ops = &uvc_func_item_ops,
3345 .ct_attrs = uvc_attrs,
3346 .ct_owner = THIS_MODULE,
3347 },
3348 .name = "",
3349 .children = (const struct uvcg_config_group_type*[]) {
3350 &uvcg_control_grp_type,
3351 &uvcg_streaming_grp_type,
3352 NULL,
3353 },
3354};
3355
3356int uvcg_attach_configfs(struct f_uvc_opts *opts)
3357{
3358 int ret;
3359
3360 config_group_init_type_name(&opts->func_inst.group, uvc_func_type.name,
3361 &uvc_func_type.type);
3362
3363 ret = uvcg_config_create_children(&opts->func_inst.group,
3364 &uvc_func_type);
3365 if (ret < 0)
3366 config_group_put(&opts->func_inst.group);
3367
3368 return ret;
3369}