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