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 46static struct uvcg_control_header *to_uvcg_control_header(struct config_item *item) 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 138static struct config_item_type uvcg_control_header_type = { 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) 151 return ERR_PTR(-ENOMEM); 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 164static void uvcg_control_header_drop(struct config_group *group, 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 721static struct uvcg_format *to_uvcg_format(struct config_item *item) 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 798static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item *item) 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) { 843 ret = -ENOMEM; 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 950static struct config_item_type uvcg_streaming_header_type = { 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) 963 return ERR_PTR(-ENOMEM); 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 976static void uvcg_streaming_header_drop(struct config_group *group, 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 1020static struct uvcg_frame *to_uvcg_frame(struct config_item *item) 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, to_cpu_endian, to_little_endian, bits) \ 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", to_cpu_endian(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 u##bits num; \ 1063 \ 1064 ret = kstrtou##bits(page, 0, &num); \ 1065 if (ret) \ 1066 return ret; \ 1067 \ 1068 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1069 \ 1070 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \ 1071 opts = to_f_uvc_opts(opts_item); \ 1072 fmt = to_uvcg_format(f->item.ci_parent); \ 1073 \ 1074 mutex_lock(&opts->lock); \ 1075 if (fmt->linked || opts->refcnt) { \ 1076 ret = -EBUSY; \ 1077 goto end; \ 1078 } \ 1079 \ 1080 f->frame.cname = to_little_endian(num); \ 1081 ret = len; \ 1082end: \ 1083 mutex_unlock(&opts->lock); \ 1084 mutex_unlock(su_mutex); \ 1085 return ret; \ 1086} \ 1087 \ 1088static struct uvcg_frame_attribute \ 1089 uvcg_frame_##cname = \ 1090 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \ 1091 uvcg_frame_##cname##_show, \ 1092 uvcg_frame_##cname##_store) 1093 1094#define noop_conversion(x) (x) 1095 1096UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion, 1097 noop_conversion, 8); 1098UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16); 1099UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16); 1100UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32); 1101UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32); 1102UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 1103 le32_to_cpu, cpu_to_le32, 32); 1104UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 1105 le32_to_cpu, cpu_to_le32, 32); 1106 1107#undef noop_conversion 1108 1109#undef UVCG_FRAME_ATTR 1110 1111static ssize_t uvcg_frame_dw_frame_interval_show(struct uvcg_frame *frm, 1112 char *page) 1113{ 1114 struct f_uvc_opts *opts; 1115 struct config_item *opts_item; 1116 struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex; 1117 int result, i; 1118 char *pg = page; 1119 1120 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1121 1122 opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent; 1123 opts = to_f_uvc_opts(opts_item); 1124 1125 mutex_lock(&opts->lock); 1126 for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) { 1127 result += sprintf(pg, "%d\n", 1128 le32_to_cpu(frm->dw_frame_interval[i])); 1129 pg = page + result; 1130 } 1131 mutex_unlock(&opts->lock); 1132 1133 mutex_unlock(su_mutex); 1134 return result; 1135} 1136 1137static inline int __uvcg_count_frm_intrv(char *buf, void *priv) 1138{ 1139 ++*((int *)priv); 1140 return 0; 1141} 1142 1143static inline int __uvcg_fill_frm_intrv(char *buf, void *priv) 1144{ 1145 u32 num, **interv; 1146 int ret; 1147 1148 ret = kstrtou32(buf, 0, &num); 1149 if (ret) 1150 return ret; 1151 1152 interv = priv; 1153 **interv = cpu_to_le32(num); 1154 ++*interv; 1155 1156 return 0; 1157} 1158 1159static int __uvcg_iter_frm_intrv(const char *page, size_t len, 1160 int (*fun)(char *, void *), void *priv) 1161{ 1162 /* sign, base 2 representation, newline, terminator */ 1163 char buf[1 + sizeof(u32) * 8 + 1 + 1]; 1164 const char *pg = page; 1165 int i, ret; 1166 1167 if (!fun) 1168 return -EINVAL; 1169 1170 while (pg - page < len) { 1171 i = 0; 1172 while (i < sizeof(buf) && (pg - page < len) && 1173 *pg != '\0' && *pg != '\n') 1174 buf[i++] = *pg++; 1175 if (i == sizeof(buf)) 1176 return -EINVAL; 1177 while ((pg - page < len) && (*pg == '\0' || *pg == '\n')) 1178 ++pg; 1179 buf[i] = '\0'; 1180 ret = fun(buf, priv); 1181 if (ret) 1182 return ret; 1183 } 1184 1185 return 0; 1186} 1187 1188static ssize_t uvcg_frame_dw_frame_interval_store(struct uvcg_frame *ch, 1189 const char *page, size_t len) 1190{ 1191 struct f_uvc_opts *opts; 1192 struct config_item *opts_item; 1193 struct uvcg_format *fmt; 1194 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex; 1195 int ret = 0, n = 0; 1196 u32 *frm_intrv, *tmp; 1197 1198 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1199 1200 opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent; 1201 opts = to_f_uvc_opts(opts_item); 1202 fmt = to_uvcg_format(ch->item.ci_parent); 1203 1204 mutex_lock(&opts->lock); 1205 if (fmt->linked || opts->refcnt) { 1206 ret = -EBUSY; 1207 goto end; 1208 } 1209 1210 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n); 1211 if (ret) 1212 goto end; 1213 1214 tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL); 1215 if (!frm_intrv) { 1216 ret = -ENOMEM; 1217 goto end; 1218 } 1219 1220 ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp); 1221 if (ret) { 1222 kfree(frm_intrv); 1223 goto end; 1224 } 1225 1226 kfree(ch->dw_frame_interval); 1227 ch->dw_frame_interval = frm_intrv; 1228 ch->frame.b_frame_interval_type = n; 1229 ret = len; 1230 1231end: 1232 mutex_unlock(&opts->lock); 1233 mutex_unlock(su_mutex); 1234 return ret; 1235} 1236 1237static struct uvcg_frame_attribute 1238 uvcg_frame_dw_frame_interval = 1239 __CONFIGFS_ATTR(dwFrameInterval, S_IRUGO | S_IWUSR, 1240 uvcg_frame_dw_frame_interval_show, 1241 uvcg_frame_dw_frame_interval_store); 1242 1243static struct configfs_attribute *uvcg_frame_attrs[] = { 1244 &uvcg_frame_bm_capabilities.attr, 1245 &uvcg_frame_w_width.attr, 1246 &uvcg_frame_w_height.attr, 1247 &uvcg_frame_dw_min_bit_rate.attr, 1248 &uvcg_frame_dw_max_bit_rate.attr, 1249 &uvcg_frame_dw_max_video_frame_buffer_size.attr, 1250 &uvcg_frame_dw_default_frame_interval.attr, 1251 &uvcg_frame_dw_frame_interval.attr, 1252 NULL, 1253}; 1254 1255static struct config_item_type uvcg_frame_type = { 1256 .ct_item_ops = &uvcg_frame_item_ops, 1257 .ct_attrs = uvcg_frame_attrs, 1258 .ct_owner = THIS_MODULE, 1259}; 1260 1261static struct config_item *uvcg_frame_make(struct config_group *group, 1262 const char *name) 1263{ 1264 struct uvcg_frame *h; 1265 struct uvcg_format *fmt; 1266 struct f_uvc_opts *opts; 1267 struct config_item *opts_item; 1268 1269 h = kzalloc(sizeof(*h), GFP_KERNEL); 1270 if (!h) 1271 return ERR_PTR(-ENOMEM); 1272 1273 h->frame.b_descriptor_type = USB_DT_CS_INTERFACE; 1274 h->frame.b_frame_index = 1; 1275 h->frame.w_width = cpu_to_le16(640); 1276 h->frame.w_height = cpu_to_le16(360); 1277 h->frame.dw_min_bit_rate = cpu_to_le32(18432000); 1278 h->frame.dw_max_bit_rate = cpu_to_le32(55296000); 1279 h->frame.dw_max_video_frame_buffer_size = cpu_to_le32(460800); 1280 h->frame.dw_default_frame_interval = cpu_to_le32(666666); 1281 1282 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; 1283 opts = to_f_uvc_opts(opts_item); 1284 1285 mutex_lock(&opts->lock); 1286 fmt = to_uvcg_format(&group->cg_item); 1287 if (fmt->type == UVCG_UNCOMPRESSED) { 1288 h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED; 1289 h->fmt_type = UVCG_UNCOMPRESSED; 1290 } else if (fmt->type == UVCG_MJPEG) { 1291 h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG; 1292 h->fmt_type = UVCG_MJPEG; 1293 } else { 1294 mutex_unlock(&opts->lock); 1295 kfree(h); 1296 return ERR_PTR(-EINVAL); 1297 } 1298 ++fmt->num_frames; 1299 mutex_unlock(&opts->lock); 1300 1301 config_item_init_type_name(&h->item, name, &uvcg_frame_type); 1302 1303 return &h->item; 1304} 1305 1306static void uvcg_frame_drop(struct config_group *group, struct config_item *item) 1307{ 1308 struct uvcg_frame *h = to_uvcg_frame(item); 1309 struct uvcg_format *fmt; 1310 struct f_uvc_opts *opts; 1311 struct config_item *opts_item; 1312 1313 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; 1314 opts = to_f_uvc_opts(opts_item); 1315 1316 mutex_lock(&opts->lock); 1317 fmt = to_uvcg_format(&group->cg_item); 1318 --fmt->num_frames; 1319 kfree(h); 1320 mutex_unlock(&opts->lock); 1321} 1322 1323/* streaming/uncompressed/<NAME> */ 1324struct uvcg_uncompressed { 1325 struct uvcg_format fmt; 1326 struct uvc_format_uncompressed desc; 1327}; 1328 1329static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item) 1330{ 1331 return container_of( 1332 container_of(to_config_group(item), struct uvcg_format, group), 1333 struct uvcg_uncompressed, fmt); 1334} 1335 1336CONFIGFS_ATTR_STRUCT(uvcg_uncompressed); 1337CONFIGFS_ATTR_OPS(uvcg_uncompressed); 1338 1339static struct configfs_item_operations uvcg_uncompressed_item_ops = { 1340 .show_attribute = uvcg_uncompressed_attr_show, 1341 .store_attribute = uvcg_uncompressed_attr_store, 1342}; 1343 1344static struct configfs_group_operations uvcg_uncompressed_group_ops = { 1345 .make_item = uvcg_frame_make, 1346 .drop_item = uvcg_frame_drop, 1347}; 1348 1349static ssize_t uvcg_uncompressed_guid_format_show(struct uvcg_uncompressed *ch, 1350 char *page) 1351{ 1352 struct f_uvc_opts *opts; 1353 struct config_item *opts_item; 1354 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex; 1355 1356 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1357 1358 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; 1359 opts = to_f_uvc_opts(opts_item); 1360 1361 mutex_lock(&opts->lock); 1362 memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat)); 1363 mutex_unlock(&opts->lock); 1364 1365 mutex_unlock(su_mutex); 1366 1367 return sizeof(ch->desc.guidFormat); 1368} 1369 1370static ssize_t uvcg_uncompressed_guid_format_store(struct uvcg_uncompressed *ch, 1371 const char *page, size_t len) 1372{ 1373 struct f_uvc_opts *opts; 1374 struct config_item *opts_item; 1375 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex; 1376 int ret; 1377 1378 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1379 1380 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; 1381 opts = to_f_uvc_opts(opts_item); 1382 1383 mutex_lock(&opts->lock); 1384 if (ch->fmt.linked || opts->refcnt) { 1385 ret = -EBUSY; 1386 goto end; 1387 } 1388 1389 memcpy(ch->desc.guidFormat, page, 1390 min(sizeof(ch->desc.guidFormat), len)); 1391 ret = sizeof(ch->desc.guidFormat); 1392 1393end: 1394 mutex_unlock(&opts->lock); 1395 mutex_unlock(su_mutex); 1396 return ret; 1397} 1398 1399static struct uvcg_uncompressed_attribute uvcg_uncompressed_guid_format = 1400 __CONFIGFS_ATTR(guidFormat, S_IRUGO | S_IWUSR, 1401 uvcg_uncompressed_guid_format_show, 1402 uvcg_uncompressed_guid_format_store); 1403 1404 1405#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \ 1406static ssize_t uvcg_uncompressed_##cname##_show( \ 1407 struct uvcg_uncompressed *u, char *page) \ 1408{ \ 1409 struct f_uvc_opts *opts; \ 1410 struct config_item *opts_item; \ 1411 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 1412 int result; \ 1413 \ 1414 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1415 \ 1416 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 1417 opts = to_f_uvc_opts(opts_item); \ 1418 \ 1419 mutex_lock(&opts->lock); \ 1420 result = sprintf(page, "%d\n", conv(u->desc.aname)); \ 1421 mutex_unlock(&opts->lock); \ 1422 \ 1423 mutex_unlock(su_mutex); \ 1424 return result; \ 1425} \ 1426 \ 1427static struct uvcg_uncompressed_attribute \ 1428 uvcg_uncompressed_##cname = \ 1429 __CONFIGFS_ATTR_RO(aname, uvcg_uncompressed_##cname##_show) 1430 1431#define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \ 1432static ssize_t uvcg_uncompressed_##cname##_show( \ 1433 struct uvcg_uncompressed *u, char *page) \ 1434{ \ 1435 struct f_uvc_opts *opts; \ 1436 struct config_item *opts_item; \ 1437 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 1438 int result; \ 1439 \ 1440 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1441 \ 1442 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 1443 opts = to_f_uvc_opts(opts_item); \ 1444 \ 1445 mutex_lock(&opts->lock); \ 1446 result = sprintf(page, "%d\n", conv(u->desc.aname)); \ 1447 mutex_unlock(&opts->lock); \ 1448 \ 1449 mutex_unlock(su_mutex); \ 1450 return result; \ 1451} \ 1452 \ 1453static ssize_t \ 1454uvcg_uncompressed_##cname##_store(struct uvcg_uncompressed *u, \ 1455 const char *page, size_t len) \ 1456{ \ 1457 struct f_uvc_opts *opts; \ 1458 struct config_item *opts_item; \ 1459 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 1460 int ret; \ 1461 u8 num; \ 1462 \ 1463 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1464 \ 1465 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 1466 opts = to_f_uvc_opts(opts_item); \ 1467 \ 1468 mutex_lock(&opts->lock); \ 1469 if (u->fmt.linked || opts->refcnt) { \ 1470 ret = -EBUSY; \ 1471 goto end; \ 1472 } \ 1473 \ 1474 ret = kstrtou8(page, 0, &num); \ 1475 if (ret) \ 1476 goto end; \ 1477 \ 1478 if (num > 255) { \ 1479 ret = -EINVAL; \ 1480 goto end; \ 1481 } \ 1482 u->desc.aname = num; \ 1483 ret = len; \ 1484end: \ 1485 mutex_unlock(&opts->lock); \ 1486 mutex_unlock(su_mutex); \ 1487 return ret; \ 1488} \ 1489 \ 1490static struct uvcg_uncompressed_attribute \ 1491 uvcg_uncompressed_##cname = \ 1492 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \ 1493 uvcg_uncompressed_##cname##_show, \ 1494 uvcg_uncompressed_##cname##_store) 1495 1496#define identity_conv(x) (x) 1497 1498UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv); 1499UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 1500 identity_conv); 1501UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv); 1502UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv); 1503UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv); 1504 1505#undef identity_conv 1506 1507#undef UVCG_UNCOMPRESSED_ATTR 1508#undef UVCG_UNCOMPRESSED_ATTR_RO 1509 1510static inline ssize_t 1511uvcg_uncompressed_bma_controls_show(struct uvcg_uncompressed *unc, char *page) 1512{ 1513 return uvcg_format_bma_controls_show(&unc->fmt, page); 1514} 1515 1516static inline ssize_t 1517uvcg_uncompressed_bma_controls_store(struct uvcg_uncompressed *ch, 1518 const char *page, size_t len) 1519{ 1520 return uvcg_format_bma_controls_store(&ch->fmt, page, len); 1521} 1522 1523static struct uvcg_uncompressed_attribute uvcg_uncompressed_bma_controls = 1524 __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR, 1525 uvcg_uncompressed_bma_controls_show, 1526 uvcg_uncompressed_bma_controls_store); 1527 1528static struct configfs_attribute *uvcg_uncompressed_attrs[] = { 1529 &uvcg_uncompressed_guid_format.attr, 1530 &uvcg_uncompressed_b_bits_per_pixel.attr, 1531 &uvcg_uncompressed_b_default_frame_index.attr, 1532 &uvcg_uncompressed_b_aspect_ratio_x.attr, 1533 &uvcg_uncompressed_b_aspect_ratio_y.attr, 1534 &uvcg_uncompressed_bm_interface_flags.attr, 1535 &uvcg_uncompressed_bma_controls.attr, 1536 NULL, 1537}; 1538 1539static struct config_item_type uvcg_uncompressed_type = { 1540 .ct_item_ops = &uvcg_uncompressed_item_ops, 1541 .ct_group_ops = &uvcg_uncompressed_group_ops, 1542 .ct_attrs = uvcg_uncompressed_attrs, 1543 .ct_owner = THIS_MODULE, 1544}; 1545 1546static struct config_group *uvcg_uncompressed_make(struct config_group *group, 1547 const char *name) 1548{ 1549 static char guid[] = { 1550 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 1551 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 1552 }; 1553 struct uvcg_uncompressed *h; 1554 1555 h = kzalloc(sizeof(*h), GFP_KERNEL); 1556 if (!h) 1557 return ERR_PTR(-ENOMEM); 1558 1559 h->desc.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE; 1560 h->desc.bDescriptorType = USB_DT_CS_INTERFACE; 1561 h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED; 1562 memcpy(h->desc.guidFormat, guid, sizeof(guid)); 1563 h->desc.bBitsPerPixel = 16; 1564 h->desc.bDefaultFrameIndex = 1; 1565 h->desc.bAspectRatioX = 0; 1566 h->desc.bAspectRatioY = 0; 1567 h->desc.bmInterfaceFlags = 0; 1568 h->desc.bCopyProtect = 0; 1569 1570 h->fmt.type = UVCG_UNCOMPRESSED; 1571 config_group_init_type_name(&h->fmt.group, name, 1572 &uvcg_uncompressed_type); 1573 1574 return &h->fmt.group; 1575} 1576 1577static void uvcg_uncompressed_drop(struct config_group *group, 1578 struct config_item *item) 1579{ 1580 struct uvcg_uncompressed *h = to_uvcg_uncompressed(item); 1581 1582 kfree(h); 1583} 1584 1585static struct configfs_group_operations uvcg_uncompressed_grp_ops = { 1586 .make_group = uvcg_uncompressed_make, 1587 .drop_item = uvcg_uncompressed_drop, 1588}; 1589 1590static struct config_item_type uvcg_uncompressed_grp_type = { 1591 .ct_group_ops = &uvcg_uncompressed_grp_ops, 1592 .ct_owner = THIS_MODULE, 1593}; 1594 1595/* streaming/mjpeg/<NAME> */ 1596struct uvcg_mjpeg { 1597 struct uvcg_format fmt; 1598 struct uvc_format_mjpeg desc; 1599}; 1600 1601static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item) 1602{ 1603 return container_of( 1604 container_of(to_config_group(item), struct uvcg_format, group), 1605 struct uvcg_mjpeg, fmt); 1606} 1607 1608CONFIGFS_ATTR_STRUCT(uvcg_mjpeg); 1609CONFIGFS_ATTR_OPS(uvcg_mjpeg); 1610 1611static struct configfs_item_operations uvcg_mjpeg_item_ops = { 1612 .show_attribute = uvcg_mjpeg_attr_show, 1613 .store_attribute = uvcg_mjpeg_attr_store, 1614}; 1615 1616static struct configfs_group_operations uvcg_mjpeg_group_ops = { 1617 .make_item = uvcg_frame_make, 1618 .drop_item = uvcg_frame_drop, 1619}; 1620 1621#define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \ 1622static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\ 1623{ \ 1624 struct f_uvc_opts *opts; \ 1625 struct config_item *opts_item; \ 1626 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 1627 int result; \ 1628 \ 1629 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1630 \ 1631 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 1632 opts = to_f_uvc_opts(opts_item); \ 1633 \ 1634 mutex_lock(&opts->lock); \ 1635 result = sprintf(page, "%d\n", conv(u->desc.aname)); \ 1636 mutex_unlock(&opts->lock); \ 1637 \ 1638 mutex_unlock(su_mutex); \ 1639 return result; \ 1640} \ 1641 \ 1642static struct uvcg_mjpeg_attribute \ 1643 uvcg_mjpeg_##cname = \ 1644 __CONFIGFS_ATTR_RO(aname, uvcg_mjpeg_##cname##_show) 1645 1646#define UVCG_MJPEG_ATTR(cname, aname, conv) \ 1647static ssize_t uvcg_mjpeg_##cname##_show(struct uvcg_mjpeg *u, char *page)\ 1648{ \ 1649 struct f_uvc_opts *opts; \ 1650 struct config_item *opts_item; \ 1651 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 1652 int result; \ 1653 \ 1654 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1655 \ 1656 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 1657 opts = to_f_uvc_opts(opts_item); \ 1658 \ 1659 mutex_lock(&opts->lock); \ 1660 result = sprintf(page, "%d\n", conv(u->desc.aname)); \ 1661 mutex_unlock(&opts->lock); \ 1662 \ 1663 mutex_unlock(su_mutex); \ 1664 return result; \ 1665} \ 1666 \ 1667static ssize_t \ 1668uvcg_mjpeg_##cname##_store(struct uvcg_mjpeg *u, \ 1669 const char *page, size_t len) \ 1670{ \ 1671 struct f_uvc_opts *opts; \ 1672 struct config_item *opts_item; \ 1673 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 1674 int ret; \ 1675 u8 num; \ 1676 \ 1677 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1678 \ 1679 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 1680 opts = to_f_uvc_opts(opts_item); \ 1681 \ 1682 mutex_lock(&opts->lock); \ 1683 if (u->fmt.linked || opts->refcnt) { \ 1684 ret = -EBUSY; \ 1685 goto end; \ 1686 } \ 1687 \ 1688 ret = kstrtou8(page, 0, &num); \ 1689 if (ret) \ 1690 goto end; \ 1691 \ 1692 if (num > 255) { \ 1693 ret = -EINVAL; \ 1694 goto end; \ 1695 } \ 1696 u->desc.aname = num; \ 1697 ret = len; \ 1698end: \ 1699 mutex_unlock(&opts->lock); \ 1700 mutex_unlock(su_mutex); \ 1701 return ret; \ 1702} \ 1703 \ 1704static struct uvcg_mjpeg_attribute \ 1705 uvcg_mjpeg_##cname = \ 1706 __CONFIGFS_ATTR(aname, S_IRUGO | S_IWUSR, \ 1707 uvcg_mjpeg_##cname##_show, \ 1708 uvcg_mjpeg_##cname##_store) 1709 1710#define identity_conv(x) (x) 1711 1712UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 1713 identity_conv); 1714UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv); 1715UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv); 1716UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv); 1717UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv); 1718 1719#undef identity_conv 1720 1721#undef UVCG_MJPEG_ATTR 1722#undef UVCG_MJPEG_ATTR_RO 1723 1724static inline ssize_t 1725uvcg_mjpeg_bma_controls_show(struct uvcg_mjpeg *unc, char *page) 1726{ 1727 return uvcg_format_bma_controls_show(&unc->fmt, page); 1728} 1729 1730static inline ssize_t 1731uvcg_mjpeg_bma_controls_store(struct uvcg_mjpeg *ch, 1732 const char *page, size_t len) 1733{ 1734 return uvcg_format_bma_controls_store(&ch->fmt, page, len); 1735} 1736 1737static struct uvcg_mjpeg_attribute uvcg_mjpeg_bma_controls = 1738 __CONFIGFS_ATTR(bmaControls, S_IRUGO | S_IWUSR, 1739 uvcg_mjpeg_bma_controls_show, 1740 uvcg_mjpeg_bma_controls_store); 1741 1742static struct configfs_attribute *uvcg_mjpeg_attrs[] = { 1743 &uvcg_mjpeg_b_default_frame_index.attr, 1744 &uvcg_mjpeg_bm_flags.attr, 1745 &uvcg_mjpeg_b_aspect_ratio_x.attr, 1746 &uvcg_mjpeg_b_aspect_ratio_y.attr, 1747 &uvcg_mjpeg_bm_interface_flags.attr, 1748 &uvcg_mjpeg_bma_controls.attr, 1749 NULL, 1750}; 1751 1752static struct config_item_type uvcg_mjpeg_type = { 1753 .ct_item_ops = &uvcg_mjpeg_item_ops, 1754 .ct_group_ops = &uvcg_mjpeg_group_ops, 1755 .ct_attrs = uvcg_mjpeg_attrs, 1756 .ct_owner = THIS_MODULE, 1757}; 1758 1759static struct config_group *uvcg_mjpeg_make(struct config_group *group, 1760 const char *name) 1761{ 1762 struct uvcg_mjpeg *h; 1763 1764 h = kzalloc(sizeof(*h), GFP_KERNEL); 1765 if (!h) 1766 return ERR_PTR(-ENOMEM); 1767 1768 h->desc.bLength = UVC_DT_FORMAT_MJPEG_SIZE; 1769 h->desc.bDescriptorType = USB_DT_CS_INTERFACE; 1770 h->desc.bDescriptorSubType = UVC_VS_FORMAT_MJPEG; 1771 h->desc.bDefaultFrameIndex = 1; 1772 h->desc.bAspectRatioX = 0; 1773 h->desc.bAspectRatioY = 0; 1774 h->desc.bmInterfaceFlags = 0; 1775 h->desc.bCopyProtect = 0; 1776 1777 h->fmt.type = UVCG_MJPEG; 1778 config_group_init_type_name(&h->fmt.group, name, 1779 &uvcg_mjpeg_type); 1780 1781 return &h->fmt.group; 1782} 1783 1784static void uvcg_mjpeg_drop(struct config_group *group, 1785 struct config_item *item) 1786{ 1787 struct uvcg_mjpeg *h = to_uvcg_mjpeg(item); 1788 1789 kfree(h); 1790} 1791 1792static struct configfs_group_operations uvcg_mjpeg_grp_ops = { 1793 .make_group = uvcg_mjpeg_make, 1794 .drop_item = uvcg_mjpeg_drop, 1795}; 1796 1797static struct config_item_type uvcg_mjpeg_grp_type = { 1798 .ct_group_ops = &uvcg_mjpeg_grp_ops, 1799 .ct_owner = THIS_MODULE, 1800}; 1801 1802/* streaming/color_matching/default */ 1803static struct uvcg_default_color_matching { 1804 struct config_group group; 1805} uvcg_default_color_matching; 1806 1807static inline struct uvcg_default_color_matching 1808*to_uvcg_default_color_matching(struct config_item *item) 1809{ 1810 return container_of(to_config_group(item), 1811 struct uvcg_default_color_matching, group); 1812} 1813 1814CONFIGFS_ATTR_STRUCT(uvcg_default_color_matching); 1815CONFIGFS_ATTR_OPS_RO(uvcg_default_color_matching); 1816 1817static struct configfs_item_operations uvcg_default_color_matching_item_ops = { 1818 .show_attribute = uvcg_default_color_matching_attr_show, 1819}; 1820 1821#define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \ 1822static ssize_t uvcg_default_color_matching_##cname##_show( \ 1823 struct uvcg_default_color_matching *dc, char *page) \ 1824{ \ 1825 struct f_uvc_opts *opts; \ 1826 struct config_item *opts_item; \ 1827 struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \ 1828 struct uvc_color_matching_descriptor *cd; \ 1829 int result; \ 1830 \ 1831 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1832 \ 1833 opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \ 1834 opts = to_f_uvc_opts(opts_item); \ 1835 cd = &opts->uvc_color_matching; \ 1836 \ 1837 mutex_lock(&opts->lock); \ 1838 result = sprintf(page, "%d\n", conv(cd->aname)); \ 1839 mutex_unlock(&opts->lock); \ 1840 \ 1841 mutex_unlock(su_mutex); \ 1842 return result; \ 1843} \ 1844 \ 1845static struct uvcg_default_color_matching_attribute \ 1846 uvcg_default_color_matching_##cname = \ 1847 __CONFIGFS_ATTR_RO(aname, uvcg_default_color_matching_##cname##_show) 1848 1849#define identity_conv(x) (x) 1850 1851UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 1852 identity_conv); 1853UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics, 1854 bTransferCharacteristics, identity_conv); 1855UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 1856 identity_conv); 1857 1858#undef identity_conv 1859 1860#undef UVCG_DEFAULT_COLOR_MATCHING_ATTR 1861 1862static struct configfs_attribute *uvcg_default_color_matching_attrs[] = { 1863 &uvcg_default_color_matching_b_color_primaries.attr, 1864 &uvcg_default_color_matching_b_transfer_characteristics.attr, 1865 &uvcg_default_color_matching_b_matrix_coefficients.attr, 1866 NULL, 1867}; 1868 1869static struct config_item_type uvcg_default_color_matching_type = { 1870 .ct_item_ops = &uvcg_default_color_matching_item_ops, 1871 .ct_attrs = uvcg_default_color_matching_attrs, 1872 .ct_owner = THIS_MODULE, 1873}; 1874 1875/* struct uvcg_color_matching {}; */ 1876 1877static struct config_group *uvcg_color_matching_default_groups[] = { 1878 &uvcg_default_color_matching.group, 1879 NULL, 1880}; 1881 1882/* streaming/color_matching */ 1883static struct uvcg_color_matching_grp { 1884 struct config_group group; 1885} uvcg_color_matching_grp; 1886 1887static struct config_item_type uvcg_color_matching_grp_type = { 1888 .ct_owner = THIS_MODULE, 1889}; 1890 1891/* streaming/class/{fs|hs|ss} */ 1892static struct uvcg_streaming_class { 1893 struct config_group group; 1894} uvcg_streaming_class_fs, uvcg_streaming_class_hs, uvcg_streaming_class_ss; 1895 1896 1897static inline struct uvc_descriptor_header 1898***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o) 1899{ 1900 struct uvcg_streaming_class *cl = container_of(to_config_group(i), 1901 struct uvcg_streaming_class, group); 1902 1903 if (cl == &uvcg_streaming_class_fs) 1904 return &o->uvc_fs_streaming_cls; 1905 1906 if (cl == &uvcg_streaming_class_hs) 1907 return &o->uvc_hs_streaming_cls; 1908 1909 if (cl == &uvcg_streaming_class_ss) 1910 return &o->uvc_ss_streaming_cls; 1911 1912 return NULL; 1913} 1914 1915enum uvcg_strm_type { 1916 UVCG_HEADER = 0, 1917 UVCG_FORMAT, 1918 UVCG_FRAME 1919}; 1920 1921/* 1922 * Iterate over a hierarchy of streaming descriptors' config items. 1923 * The items are created by the user with configfs. 1924 * 1925 * It "processes" the header pointed to by @priv1, then for each format 1926 * that follows the header "processes" the format itself and then for 1927 * each frame inside a format "processes" the frame. 1928 * 1929 * As a "processing" function the @fun is used. 1930 * 1931 * __uvcg_iter_strm_cls() is used in two context: first, to calculate 1932 * the amount of memory needed for an array of streaming descriptors 1933 * and second, to actually fill the array. 1934 * 1935 * @h: streaming header pointer 1936 * @priv2: an "inout" parameter (the caller might want to see the changes to it) 1937 * @priv3: an "inout" parameter (the caller might want to see the changes to it) 1938 * @fun: callback function for processing each level of the hierarchy 1939 */ 1940static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h, 1941 void *priv2, void *priv3, 1942 int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type)) 1943{ 1944 struct uvcg_format_ptr *f; 1945 struct config_group *grp; 1946 struct config_item *item; 1947 struct uvcg_frame *frm; 1948 int ret, i, j; 1949 1950 if (!fun) 1951 return -EINVAL; 1952 1953 i = j = 0; 1954 ret = fun(h, priv2, priv3, 0, UVCG_HEADER); 1955 if (ret) 1956 return ret; 1957 list_for_each_entry(f, &h->formats, entry) { 1958 ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT); 1959 if (ret) 1960 return ret; 1961 grp = &f->fmt->group; 1962 list_for_each_entry(item, &grp->cg_children, ci_entry) { 1963 frm = to_uvcg_frame(item); 1964 ret = fun(frm, priv2, priv3, j++, UVCG_FRAME); 1965 if (ret) 1966 return ret; 1967 } 1968 } 1969 1970 return ret; 1971} 1972 1973/* 1974 * Count how many bytes are needed for an array of streaming descriptors. 1975 * 1976 * @priv1: pointer to a header, format or frame 1977 * @priv2: inout parameter, accumulated size of the array 1978 * @priv3: inout parameter, accumulated number of the array elements 1979 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls 1980 */ 1981static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n, 1982 enum uvcg_strm_type type) 1983{ 1984 size_t *size = priv2; 1985 size_t *count = priv3; 1986 1987 switch (type) { 1988 case UVCG_HEADER: { 1989 struct uvcg_streaming_header *h = priv1; 1990 1991 *size += sizeof(h->desc); 1992 /* bmaControls */ 1993 *size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE; 1994 } 1995 break; 1996 case UVCG_FORMAT: { 1997 struct uvcg_format *fmt = priv1; 1998 1999 if (fmt->type == UVCG_UNCOMPRESSED) { 2000 struct uvcg_uncompressed *u = 2001 container_of(fmt, struct uvcg_uncompressed, 2002 fmt); 2003 2004 *size += sizeof(u->desc); 2005 } else if (fmt->type == UVCG_MJPEG) { 2006 struct uvcg_mjpeg *m = 2007 container_of(fmt, struct uvcg_mjpeg, fmt); 2008 2009 *size += sizeof(m->desc); 2010 } else { 2011 return -EINVAL; 2012 } 2013 } 2014 break; 2015 case UVCG_FRAME: { 2016 struct uvcg_frame *frm = priv1; 2017 int sz = sizeof(frm->dw_frame_interval); 2018 2019 *size += sizeof(frm->frame); 2020 *size += frm->frame.b_frame_interval_type * sz; 2021 } 2022 break; 2023 } 2024 2025 ++*count; 2026 2027 return 0; 2028} 2029 2030/* 2031 * Fill an array of streaming descriptors. 2032 * 2033 * @priv1: pointer to a header, format or frame 2034 * @priv2: inout parameter, pointer into a block of memory 2035 * @priv3: inout parameter, pointer to a 2-dimensional array 2036 */ 2037static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n, 2038 enum uvcg_strm_type type) 2039{ 2040 void **dest = priv2; 2041 struct uvc_descriptor_header ***array = priv3; 2042 size_t sz; 2043 2044 **array = *dest; 2045 ++*array; 2046 2047 switch (type) { 2048 case UVCG_HEADER: { 2049 struct uvc_input_header_descriptor *ihdr = *dest; 2050 struct uvcg_streaming_header *h = priv1; 2051 struct uvcg_format_ptr *f; 2052 2053 memcpy(*dest, &h->desc, sizeof(h->desc)); 2054 *dest += sizeof(h->desc); 2055 sz = UVCG_STREAMING_CONTROL_SIZE; 2056 list_for_each_entry(f, &h->formats, entry) { 2057 memcpy(*dest, f->fmt->bmaControls, sz); 2058 *dest += sz; 2059 } 2060 ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz; 2061 ihdr->bNumFormats = h->num_fmt; 2062 } 2063 break; 2064 case UVCG_FORMAT: { 2065 struct uvcg_format *fmt = priv1; 2066 2067 if (fmt->type == UVCG_UNCOMPRESSED) { 2068 struct uvc_format_uncompressed *unc = *dest; 2069 struct uvcg_uncompressed *u = 2070 container_of(fmt, struct uvcg_uncompressed, 2071 fmt); 2072 2073 memcpy(*dest, &u->desc, sizeof(u->desc)); 2074 *dest += sizeof(u->desc); 2075 unc->bNumFrameDescriptors = fmt->num_frames; 2076 unc->bFormatIndex = n + 1; 2077 } else if (fmt->type == UVCG_MJPEG) { 2078 struct uvc_format_mjpeg *mjp = *dest; 2079 struct uvcg_mjpeg *m = 2080 container_of(fmt, struct uvcg_mjpeg, fmt); 2081 2082 memcpy(*dest, &m->desc, sizeof(m->desc)); 2083 *dest += sizeof(m->desc); 2084 mjp->bNumFrameDescriptors = fmt->num_frames; 2085 mjp->bFormatIndex = n + 1; 2086 } else { 2087 return -EINVAL; 2088 } 2089 } 2090 break; 2091 case UVCG_FRAME: { 2092 struct uvcg_frame *frm = priv1; 2093 struct uvc_descriptor_header *h = *dest; 2094 2095 sz = sizeof(frm->frame); 2096 memcpy(*dest, &frm->frame, sz); 2097 *dest += sz; 2098 sz = frm->frame.b_frame_interval_type * 2099 sizeof(*frm->dw_frame_interval); 2100 memcpy(*dest, frm->dw_frame_interval, sz); 2101 *dest += sz; 2102 if (frm->fmt_type == UVCG_UNCOMPRESSED) 2103 h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE( 2104 frm->frame.b_frame_interval_type); 2105 else if (frm->fmt_type == UVCG_MJPEG) 2106 h->bLength = UVC_DT_FRAME_MJPEG_SIZE( 2107 frm->frame.b_frame_interval_type); 2108 } 2109 break; 2110 } 2111 2112 return 0; 2113} 2114 2115static int uvcg_streaming_class_allow_link(struct config_item *src, 2116 struct config_item *target) 2117{ 2118 struct config_item *streaming, *header; 2119 struct f_uvc_opts *opts; 2120 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 2121 struct uvc_descriptor_header ***class_array, **cl_arr; 2122 struct uvcg_streaming_header *target_hdr; 2123 void *data, *data_save; 2124 size_t size = 0, count = 0; 2125 int ret = -EINVAL; 2126 2127 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 2128 2129 streaming = src->ci_parent->ci_parent; 2130 header = config_group_find_item(to_config_group(streaming), "header"); 2131 if (!header || target->ci_parent != header) 2132 goto out; 2133 2134 opts = to_f_uvc_opts(streaming->ci_parent); 2135 2136 mutex_lock(&opts->lock); 2137 2138 class_array = __uvcg_get_stream_class_arr(src, opts); 2139 if (!class_array || *class_array || opts->refcnt) { 2140 ret = -EBUSY; 2141 goto unlock; 2142 } 2143 2144 target_hdr = to_uvcg_streaming_header(target); 2145 ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm); 2146 if (ret) 2147 goto unlock; 2148 2149 count += 2; /* color_matching, NULL */ 2150 *class_array = kcalloc(count, sizeof(void *), GFP_KERNEL); 2151 if (!*class_array) { 2152 ret = -ENOMEM; 2153 goto unlock; 2154 } 2155 2156 data = data_save = kzalloc(size, GFP_KERNEL); 2157 if (!data) { 2158 kfree(*class_array); 2159 *class_array = NULL; 2160 ret = PTR_ERR(data); 2161 goto unlock; 2162 } 2163 cl_arr = *class_array; 2164 ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr, 2165 __uvcg_fill_strm); 2166 if (ret) { 2167 kfree(*class_array); 2168 *class_array = NULL; 2169 /* 2170 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls() 2171 * might have advanced the "data", so use a backup copy 2172 */ 2173 kfree(data_save); 2174 goto unlock; 2175 } 2176 *cl_arr = (struct uvc_descriptor_header *)&opts->uvc_color_matching; 2177 2178 ++target_hdr->linked; 2179 ret = 0; 2180 2181unlock: 2182 mutex_unlock(&opts->lock); 2183out: 2184 mutex_unlock(su_mutex); 2185 return ret; 2186} 2187 2188static int uvcg_streaming_class_drop_link(struct config_item *src, 2189 struct config_item *target) 2190{ 2191 struct config_item *streaming, *header; 2192 struct f_uvc_opts *opts; 2193 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 2194 struct uvc_descriptor_header ***class_array; 2195 struct uvcg_streaming_header *target_hdr; 2196 int ret = -EINVAL; 2197 2198 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 2199 2200 streaming = src->ci_parent->ci_parent; 2201 header = config_group_find_item(to_config_group(streaming), "header"); 2202 if (!header || target->ci_parent != header) 2203 goto out; 2204 2205 opts = to_f_uvc_opts(streaming->ci_parent); 2206 2207 mutex_lock(&opts->lock); 2208 2209 class_array = __uvcg_get_stream_class_arr(src, opts); 2210 if (!class_array || !*class_array) 2211 goto unlock; 2212 2213 if (opts->refcnt) { 2214 ret = -EBUSY; 2215 goto unlock; 2216 } 2217 2218 target_hdr = to_uvcg_streaming_header(target); 2219 --target_hdr->linked; 2220 kfree(**class_array); 2221 kfree(*class_array); 2222 *class_array = NULL; 2223 ret = 0; 2224 2225unlock: 2226 mutex_unlock(&opts->lock); 2227out: 2228 mutex_unlock(su_mutex); 2229 return ret; 2230} 2231 2232static struct configfs_item_operations uvcg_streaming_class_item_ops = { 2233 .allow_link = uvcg_streaming_class_allow_link, 2234 .drop_link = uvcg_streaming_class_drop_link, 2235}; 2236 2237static struct config_item_type uvcg_streaming_class_type = { 2238 .ct_item_ops = &uvcg_streaming_class_item_ops, 2239 .ct_owner = THIS_MODULE, 2240}; 2241 2242static struct config_group *uvcg_streaming_class_default_groups[] = { 2243 &uvcg_streaming_class_fs.group, 2244 &uvcg_streaming_class_hs.group, 2245 &uvcg_streaming_class_ss.group, 2246 NULL, 2247}; 2248 2249/* streaming/class */ 2250static struct uvcg_streaming_class_grp { 2251 struct config_group group; 2252} uvcg_streaming_class_grp; 2253 2254static struct config_item_type uvcg_streaming_class_grp_type = { 2255 .ct_owner = THIS_MODULE, 2256}; 2257 2258static struct config_group *uvcg_streaming_default_groups[] = { 2259 &uvcg_streaming_header_grp.group, 2260 &uvcg_uncompressed_grp.group, 2261 &uvcg_mjpeg_grp.group, 2262 &uvcg_color_matching_grp.group, 2263 &uvcg_streaming_class_grp.group, 2264 NULL, 2265}; 2266 2267/* streaming */ 2268static struct uvcg_streaming_grp { 2269 struct config_group group; 2270} uvcg_streaming_grp; 2271 2272static struct config_item_type uvcg_streaming_grp_type = { 2273 .ct_owner = THIS_MODULE, 2274}; 2275 2276static struct config_group *uvcg_default_groups[] = { 2277 &uvcg_control_grp.group, 2278 &uvcg_streaming_grp.group, 2279 NULL, 2280}; 2281 2282static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item) 2283{ 2284 return container_of(to_config_group(item), struct f_uvc_opts, 2285 func_inst.group); 2286} 2287 2288CONFIGFS_ATTR_STRUCT(f_uvc_opts); 2289CONFIGFS_ATTR_OPS(f_uvc_opts); 2290 2291static void uvc_attr_release(struct config_item *item) 2292{ 2293 struct f_uvc_opts *opts = to_f_uvc_opts(item); 2294 2295 usb_put_function_instance(&opts->func_inst); 2296} 2297 2298static struct configfs_item_operations uvc_item_ops = { 2299 .release = uvc_attr_release, 2300 .show_attribute = f_uvc_opts_attr_show, 2301 .store_attribute = f_uvc_opts_attr_store, 2302}; 2303 2304#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit) \ 2305static ssize_t f_uvc_opts_##cname##_show( \ 2306 struct f_uvc_opts *opts, char *page) \ 2307{ \ 2308 int result; \ 2309 \ 2310 mutex_lock(&opts->lock); \ 2311 result = sprintf(page, "%d\n", conv(opts->cname)); \ 2312 mutex_unlock(&opts->lock); \ 2313 \ 2314 return result; \ 2315} \ 2316 \ 2317static ssize_t \ 2318f_uvc_opts_##cname##_store(struct f_uvc_opts *opts, \ 2319 const char *page, size_t len) \ 2320{ \ 2321 int ret; \ 2322 uxx num; \ 2323 \ 2324 mutex_lock(&opts->lock); \ 2325 if (opts->refcnt) { \ 2326 ret = -EBUSY; \ 2327 goto end; \ 2328 } \ 2329 \ 2330 ret = str2u(page, 0, &num); \ 2331 if (ret) \ 2332 goto end; \ 2333 \ 2334 if (num > limit) { \ 2335 ret = -EINVAL; \ 2336 goto end; \ 2337 } \ 2338 opts->cname = vnoc(num); \ 2339 ret = len; \ 2340end: \ 2341 mutex_unlock(&opts->lock); \ 2342 return ret; \ 2343} \ 2344 \ 2345static struct f_uvc_opts_attribute \ 2346 f_uvc_opts_attribute_##cname = \ 2347 __CONFIGFS_ATTR(cname, S_IRUGO | S_IWUSR, \ 2348 f_uvc_opts_##cname##_show, \ 2349 f_uvc_opts_##cname##_store) 2350 2351#define identity_conv(x) (x) 2352 2353UVCG_OPTS_ATTR(streaming_interval, identity_conv, kstrtou8, u8, identity_conv, 2354 16); 2355UVCG_OPTS_ATTR(streaming_maxpacket, le16_to_cpu, kstrtou16, u16, le16_to_cpu, 2356 3072); 2357UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv, 2358 15); 2359 2360#undef identity_conv 2361 2362#undef UVCG_OPTS_ATTR 2363 2364static struct configfs_attribute *uvc_attrs[] = { 2365 &f_uvc_opts_attribute_streaming_interval.attr, 2366 &f_uvc_opts_attribute_streaming_maxpacket.attr, 2367 &f_uvc_opts_attribute_streaming_maxburst.attr, 2368 NULL, 2369}; 2370 2371static struct config_item_type uvc_func_type = { 2372 .ct_item_ops = &uvc_item_ops, 2373 .ct_attrs = uvc_attrs, 2374 .ct_owner = THIS_MODULE, 2375}; 2376 2377static inline void uvcg_init_group(struct config_group *g, 2378 struct config_group **default_groups, 2379 const char *name, 2380 struct config_item_type *type) 2381{ 2382 g->default_groups = default_groups; 2383 config_group_init_type_name(g, name, type); 2384} 2385 2386int uvcg_attach_configfs(struct f_uvc_opts *opts) 2387{ 2388 config_group_init_type_name(&uvcg_control_header_grp.group, 2389 "header", 2390 &uvcg_control_header_grp_type); 2391 config_group_init_type_name(&uvcg_default_processing.group, 2392 "default", 2393 &uvcg_default_processing_type); 2394 uvcg_init_group(&uvcg_processing_grp.group, 2395 uvcg_processing_default_groups, 2396 "processing", 2397 &uvcg_processing_grp_type); 2398 config_group_init_type_name(&uvcg_default_camera.group, 2399 "default", 2400 &uvcg_default_camera_type); 2401 uvcg_init_group(&uvcg_camera_grp.group, 2402 uvcg_camera_default_groups, 2403 "camera", 2404 &uvcg_camera_grp_type); 2405 config_group_init_type_name(&uvcg_default_output.group, 2406 "default", 2407 &uvcg_default_output_type); 2408 uvcg_init_group(&uvcg_output_grp.group, 2409 uvcg_output_default_groups, 2410 "output", 2411 &uvcg_output_grp_type); 2412 uvcg_init_group(&uvcg_terminal_grp.group, 2413 uvcg_terminal_default_groups, 2414 "terminal", 2415 &uvcg_terminal_grp_type); 2416 config_group_init_type_name(&uvcg_control_class_fs.group, 2417 "fs", 2418 &uvcg_control_class_type); 2419 config_group_init_type_name(&uvcg_control_class_ss.group, 2420 "ss", 2421 &uvcg_control_class_type); 2422 uvcg_init_group(&uvcg_control_class_grp.group, 2423 uvcg_control_class_default_groups, 2424 "class", 2425 &uvcg_control_class_grp_type); 2426 uvcg_init_group(&uvcg_control_grp.group, 2427 uvcg_control_default_groups, 2428 "control", 2429 &uvcg_control_grp_type); 2430 config_group_init_type_name(&uvcg_streaming_header_grp.group, 2431 "header", 2432 &uvcg_streaming_header_grp_type); 2433 config_group_init_type_name(&uvcg_uncompressed_grp.group, 2434 "uncompressed", 2435 &uvcg_uncompressed_grp_type); 2436 config_group_init_type_name(&uvcg_mjpeg_grp.group, 2437 "mjpeg", 2438 &uvcg_mjpeg_grp_type); 2439 config_group_init_type_name(&uvcg_default_color_matching.group, 2440 "default", 2441 &uvcg_default_color_matching_type); 2442 uvcg_init_group(&uvcg_color_matching_grp.group, 2443 uvcg_color_matching_default_groups, 2444 "color_matching", 2445 &uvcg_color_matching_grp_type); 2446 config_group_init_type_name(&uvcg_streaming_class_fs.group, 2447 "fs", 2448 &uvcg_streaming_class_type); 2449 config_group_init_type_name(&uvcg_streaming_class_hs.group, 2450 "hs", 2451 &uvcg_streaming_class_type); 2452 config_group_init_type_name(&uvcg_streaming_class_ss.group, 2453 "ss", 2454 &uvcg_streaming_class_type); 2455 uvcg_init_group(&uvcg_streaming_class_grp.group, 2456 uvcg_streaming_class_default_groups, 2457 "class", 2458 &uvcg_streaming_class_grp_type); 2459 uvcg_init_group(&uvcg_streaming_grp.group, 2460 uvcg_streaming_default_groups, 2461 "streaming", 2462 &uvcg_streaming_grp_type); 2463 uvcg_init_group(&opts->func_inst.group, 2464 uvcg_default_groups, 2465 "", 2466 &uvc_func_type); 2467 return 0; 2468} 2469