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