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