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