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