Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.11-rc6 3498 lines 94 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * uvc_configfs.c 4 * 5 * Configfs support for the uvc function. 6 * 7 * Copyright (c) 2014 Samsung Electronics Co., Ltd. 8 * http://www.samsung.com 9 * 10 * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com> 11 */ 12 13#include "uvc_configfs.h" 14 15#include <linux/sort.h> 16#include <linux/usb/uvc.h> 17#include <linux/usb/video.h> 18 19/* ----------------------------------------------------------------------------- 20 * Global Utility Structures and Macros 21 */ 22 23#define UVC_ATTR(prefix, cname, aname) \ 24static struct configfs_attribute prefix##attr_##cname = { \ 25 .ca_name = __stringify(aname), \ 26 .ca_mode = S_IRUGO | S_IWUGO, \ 27 .ca_owner = THIS_MODULE, \ 28 .show = prefix##cname##_show, \ 29 .store = prefix##cname##_store, \ 30} 31 32#define UVC_ATTR_RO(prefix, cname, aname) \ 33static struct configfs_attribute prefix##attr_##cname = { \ 34 .ca_name = __stringify(aname), \ 35 .ca_mode = S_IRUGO, \ 36 .ca_owner = THIS_MODULE, \ 37 .show = prefix##cname##_show, \ 38} 39 40#define le8_to_cpu(x) (x) 41#define cpu_to_le8(x) (x) 42 43static int uvcg_config_compare_u32(const void *l, const void *r) 44{ 45 u32 li = *(const u32 *)l; 46 u32 ri = *(const u32 *)r; 47 48 return li < ri ? -1 : li == ri ? 0 : 1; 49} 50 51static inline int __uvcg_count_item_entries(char *buf, void *priv, unsigned int size) 52{ 53 ++*((int *)priv); 54 return 0; 55} 56 57static inline int __uvcg_fill_item_entries(char *buf, void *priv, unsigned int size) 58{ 59 unsigned int num; 60 u8 **values; 61 int ret; 62 63 ret = kstrtouint(buf, 0, &num); 64 if (ret) 65 return ret; 66 67 if (num != (num & GENMASK((size * 8) - 1, 0))) 68 return -ERANGE; 69 70 values = priv; 71 memcpy(*values, &num, size); 72 *values += size; 73 74 return 0; 75} 76 77static int __uvcg_iter_item_entries(const char *page, size_t len, 78 int (*fun)(char *, void *, unsigned int), 79 void *priv, unsigned int size) 80{ 81 /* sign, base 2 representation, newline, terminator */ 82 unsigned int bufsize = 1 + size * 8 + 1 + 1; 83 const char *pg = page; 84 int i, ret = 0; 85 char *buf; 86 87 if (!fun) 88 return -EINVAL; 89 90 buf = kzalloc(bufsize, GFP_KERNEL); 91 if (!buf) 92 return -ENOMEM; 93 94 while (pg - page < len) { 95 i = 0; 96 while (i < bufsize && (pg - page < len) && 97 *pg != '\0' && *pg != '\n') 98 buf[i++] = *pg++; 99 if (i == bufsize) { 100 ret = -EINVAL; 101 goto out_free_buf; 102 } 103 while ((pg - page < len) && (*pg == '\0' || *pg == '\n')) 104 ++pg; 105 buf[i] = '\0'; 106 ret = fun(buf, priv, size); 107 if (ret) 108 goto out_free_buf; 109 } 110 111out_free_buf: 112 kfree(buf); 113 return ret; 114} 115 116struct uvcg_config_group_type { 117 struct config_item_type type; 118 const char *name; 119 const struct uvcg_config_group_type **children; 120 int (*create_children)(struct config_group *group); 121}; 122 123static void uvcg_config_item_release(struct config_item *item) 124{ 125 struct config_group *group = to_config_group(item); 126 127 kfree(group); 128} 129 130static struct configfs_item_operations uvcg_config_item_ops = { 131 .release = uvcg_config_item_release, 132}; 133 134static int uvcg_config_create_group(struct config_group *parent, 135 const struct uvcg_config_group_type *type); 136 137static int uvcg_config_create_children(struct config_group *group, 138 const struct uvcg_config_group_type *type) 139{ 140 const struct uvcg_config_group_type **child; 141 int ret; 142 143 if (type->create_children) 144 return type->create_children(group); 145 146 for (child = type->children; child && *child; ++child) { 147 ret = uvcg_config_create_group(group, *child); 148 if (ret < 0) 149 return ret; 150 } 151 152 return 0; 153} 154 155static int uvcg_config_create_group(struct config_group *parent, 156 const struct uvcg_config_group_type *type) 157{ 158 struct config_group *group; 159 160 group = kzalloc(sizeof(*group), GFP_KERNEL); 161 if (!group) 162 return -ENOMEM; 163 164 config_group_init_type_name(group, type->name, &type->type); 165 configfs_add_default_group(group, parent); 166 167 return uvcg_config_create_children(group, type); 168} 169 170static void uvcg_config_remove_children(struct config_group *group) 171{ 172 struct config_group *child, *n; 173 174 list_for_each_entry_safe(child, n, &group->default_groups, group_entry) { 175 list_del(&child->group_entry); 176 uvcg_config_remove_children(child); 177 config_item_put(&child->cg_item); 178 } 179} 180 181/* ----------------------------------------------------------------------------- 182 * control/header/<NAME> 183 * control/header 184 */ 185 186#define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \ 187static ssize_t uvcg_control_header_##cname##_show( \ 188 struct config_item *item, char *page) \ 189{ \ 190 struct uvcg_control_header *ch = to_uvcg_control_header(item); \ 191 struct f_uvc_opts *opts; \ 192 struct config_item *opts_item; \ 193 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\ 194 int result; \ 195 \ 196 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 197 \ 198 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \ 199 opts = to_f_uvc_opts(opts_item); \ 200 \ 201 mutex_lock(&opts->lock); \ 202 result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\ 203 mutex_unlock(&opts->lock); \ 204 \ 205 mutex_unlock(su_mutex); \ 206 return result; \ 207} \ 208 \ 209static ssize_t \ 210uvcg_control_header_##cname##_store(struct config_item *item, \ 211 const char *page, size_t len) \ 212{ \ 213 struct uvcg_control_header *ch = to_uvcg_control_header(item); \ 214 struct f_uvc_opts *opts; \ 215 struct config_item *opts_item; \ 216 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\ 217 int ret; \ 218 u##bits num; \ 219 \ 220 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 221 \ 222 opts_item = ch->item.ci_parent->ci_parent->ci_parent; \ 223 opts = to_f_uvc_opts(opts_item); \ 224 \ 225 mutex_lock(&opts->lock); \ 226 if (ch->linked || opts->refcnt) { \ 227 ret = -EBUSY; \ 228 goto end; \ 229 } \ 230 \ 231 ret = kstrtou##bits(page, 0, &num); \ 232 if (ret) \ 233 goto end; \ 234 \ 235 if (num > limit) { \ 236 ret = -EINVAL; \ 237 goto end; \ 238 } \ 239 ch->desc.aname = cpu_to_le##bits(num); \ 240 ret = len; \ 241end: \ 242 mutex_unlock(&opts->lock); \ 243 mutex_unlock(su_mutex); \ 244 return ret; \ 245} \ 246 \ 247UVC_ATTR(uvcg_control_header_, cname, aname) 248 249UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, 16, 0xffff); 250 251UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, 32, 0x7fffffff); 252 253#undef UVCG_CTRL_HDR_ATTR 254 255static struct configfs_attribute *uvcg_control_header_attrs[] = { 256 &uvcg_control_header_attr_bcd_uvc, 257 &uvcg_control_header_attr_dw_clock_frequency, 258 NULL, 259}; 260 261static const struct config_item_type uvcg_control_header_type = { 262 .ct_item_ops = &uvcg_config_item_ops, 263 .ct_attrs = uvcg_control_header_attrs, 264 .ct_owner = THIS_MODULE, 265}; 266 267static struct config_item *uvcg_control_header_make(struct config_group *group, 268 const char *name) 269{ 270 struct uvcg_control_header *h; 271 272 h = kzalloc(sizeof(*h), GFP_KERNEL); 273 if (!h) 274 return ERR_PTR(-ENOMEM); 275 276 h->desc.bLength = UVC_DT_HEADER_SIZE(1); 277 h->desc.bDescriptorType = USB_DT_CS_INTERFACE; 278 h->desc.bDescriptorSubType = UVC_VC_HEADER; 279 h->desc.bcdUVC = cpu_to_le16(0x0110); 280 h->desc.dwClockFrequency = cpu_to_le32(48000000); 281 282 config_item_init_type_name(&h->item, name, &uvcg_control_header_type); 283 284 return &h->item; 285} 286 287static struct configfs_group_operations uvcg_control_header_grp_ops = { 288 .make_item = uvcg_control_header_make, 289}; 290 291static const struct uvcg_config_group_type uvcg_control_header_grp_type = { 292 .type = { 293 .ct_item_ops = &uvcg_config_item_ops, 294 .ct_group_ops = &uvcg_control_header_grp_ops, 295 .ct_owner = THIS_MODULE, 296 }, 297 .name = "header", 298}; 299 300/* ----------------------------------------------------------------------------- 301 * control/processing/default 302 */ 303 304#define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, bits) \ 305static ssize_t uvcg_default_processing_##cname##_show( \ 306 struct config_item *item, char *page) \ 307{ \ 308 struct config_group *group = to_config_group(item); \ 309 struct f_uvc_opts *opts; \ 310 struct config_item *opts_item; \ 311 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ 312 struct uvc_processing_unit_descriptor *pd; \ 313 int result; \ 314 \ 315 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 316 \ 317 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \ 318 opts = to_f_uvc_opts(opts_item); \ 319 pd = &opts->uvc_processing; \ 320 \ 321 mutex_lock(&opts->lock); \ 322 result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \ 323 mutex_unlock(&opts->lock); \ 324 \ 325 mutex_unlock(su_mutex); \ 326 return result; \ 327} \ 328 \ 329UVC_ATTR_RO(uvcg_default_processing_, cname, aname) 330 331UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, 8); 332UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, 8); 333UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, 16); 334UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8); 335 336#undef UVCG_DEFAULT_PROCESSING_ATTR 337 338static ssize_t uvcg_default_processing_bm_controls_store( 339 struct config_item *item, const char *page, size_t len) 340{ 341 struct config_group *group = to_config_group(item); 342 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 343 struct uvc_processing_unit_descriptor *pd; 344 struct config_item *opts_item; 345 struct f_uvc_opts *opts; 346 u8 *bm_controls, *tmp; 347 unsigned int i; 348 int ret, n = 0; 349 350 mutex_lock(su_mutex); 351 352 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; 353 opts = to_f_uvc_opts(opts_item); 354 pd = &opts->uvc_processing; 355 356 mutex_lock(&opts->lock); 357 if (opts->refcnt) { 358 ret = -EBUSY; 359 goto unlock; 360 } 361 362 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, 363 sizeof(u8)); 364 if (ret) 365 goto unlock; 366 367 if (n > pd->bControlSize) { 368 ret = -EINVAL; 369 goto unlock; 370 } 371 372 tmp = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL); 373 if (!bm_controls) { 374 ret = -ENOMEM; 375 goto unlock; 376 } 377 378 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp, 379 sizeof(u8)); 380 if (ret) 381 goto free_mem; 382 383 for (i = 0; i < n; i++) 384 pd->bmControls[i] = bm_controls[i]; 385 386 ret = len; 387 388free_mem: 389 kfree(bm_controls); 390unlock: 391 mutex_unlock(&opts->lock); 392 mutex_unlock(su_mutex); 393 return ret; 394} 395 396static ssize_t uvcg_default_processing_bm_controls_show( 397 struct config_item *item, char *page) 398{ 399 struct config_group *group = to_config_group(item); 400 struct f_uvc_opts *opts; 401 struct config_item *opts_item; 402 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 403 struct uvc_processing_unit_descriptor *pd; 404 int result, i; 405 char *pg = page; 406 407 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 408 409 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; 410 opts = to_f_uvc_opts(opts_item); 411 pd = &opts->uvc_processing; 412 413 mutex_lock(&opts->lock); 414 for (result = 0, i = 0; i < pd->bControlSize; ++i) { 415 result += sprintf(pg, "%u\n", pd->bmControls[i]); 416 pg = page + result; 417 } 418 mutex_unlock(&opts->lock); 419 420 mutex_unlock(su_mutex); 421 422 return result; 423} 424 425UVC_ATTR(uvcg_default_processing_, bm_controls, bmControls); 426 427static struct configfs_attribute *uvcg_default_processing_attrs[] = { 428 &uvcg_default_processing_attr_b_unit_id, 429 &uvcg_default_processing_attr_b_source_id, 430 &uvcg_default_processing_attr_w_max_multiplier, 431 &uvcg_default_processing_attr_bm_controls, 432 &uvcg_default_processing_attr_i_processing, 433 NULL, 434}; 435 436static const struct uvcg_config_group_type uvcg_default_processing_type = { 437 .type = { 438 .ct_item_ops = &uvcg_config_item_ops, 439 .ct_attrs = uvcg_default_processing_attrs, 440 .ct_owner = THIS_MODULE, 441 }, 442 .name = "default", 443}; 444 445/* ----------------------------------------------------------------------------- 446 * control/processing 447 */ 448 449static const struct uvcg_config_group_type uvcg_processing_grp_type = { 450 .type = { 451 .ct_item_ops = &uvcg_config_item_ops, 452 .ct_owner = THIS_MODULE, 453 }, 454 .name = "processing", 455 .children = (const struct uvcg_config_group_type*[]) { 456 &uvcg_default_processing_type, 457 NULL, 458 }, 459}; 460 461/* ----------------------------------------------------------------------------- 462 * control/terminal/camera/default 463 */ 464 465#define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, bits) \ 466static ssize_t uvcg_default_camera_##cname##_show( \ 467 struct config_item *item, char *page) \ 468{ \ 469 struct config_group *group = to_config_group(item); \ 470 struct f_uvc_opts *opts; \ 471 struct config_item *opts_item; \ 472 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ 473 struct uvc_camera_terminal_descriptor *cd; \ 474 int result; \ 475 \ 476 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 477 \ 478 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \ 479 ci_parent; \ 480 opts = to_f_uvc_opts(opts_item); \ 481 cd = &opts->uvc_camera_terminal; \ 482 \ 483 mutex_lock(&opts->lock); \ 484 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \ 485 mutex_unlock(&opts->lock); \ 486 \ 487 mutex_unlock(su_mutex); \ 488 \ 489 return result; \ 490} \ 491 \ 492UVC_ATTR_RO(uvcg_default_camera_, cname, aname) 493 494UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, 8); 495UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, 16); 496UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, 8); 497UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, 8); 498UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin, 499 16); 500UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax, 501 16); 502UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength, 503 16); 504 505#undef UVCG_DEFAULT_CAMERA_ATTR 506 507static ssize_t uvcg_default_camera_bm_controls_store( 508 struct config_item *item, const char *page, size_t len) 509{ 510 struct config_group *group = to_config_group(item); 511 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 512 struct uvc_camera_terminal_descriptor *cd; 513 struct config_item *opts_item; 514 struct f_uvc_opts *opts; 515 u8 *bm_controls, *tmp; 516 unsigned int i; 517 int ret, n = 0; 518 519 mutex_lock(su_mutex); 520 521 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> 522 ci_parent; 523 opts = to_f_uvc_opts(opts_item); 524 cd = &opts->uvc_camera_terminal; 525 526 mutex_lock(&opts->lock); 527 if (opts->refcnt) { 528 ret = -EBUSY; 529 goto unlock; 530 } 531 532 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, 533 sizeof(u8)); 534 if (ret) 535 goto unlock; 536 537 if (n > cd->bControlSize) { 538 ret = -EINVAL; 539 goto unlock; 540 } 541 542 tmp = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL); 543 if (!bm_controls) { 544 ret = -ENOMEM; 545 goto unlock; 546 } 547 548 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp, 549 sizeof(u8)); 550 if (ret) 551 goto free_mem; 552 553 for (i = 0; i < n; i++) 554 cd->bmControls[i] = bm_controls[i]; 555 556 ret = len; 557 558free_mem: 559 kfree(bm_controls); 560unlock: 561 mutex_unlock(&opts->lock); 562 mutex_unlock(su_mutex); 563 return ret; 564} 565 566static ssize_t uvcg_default_camera_bm_controls_show( 567 struct config_item *item, char *page) 568{ 569 struct config_group *group = to_config_group(item); 570 struct f_uvc_opts *opts; 571 struct config_item *opts_item; 572 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 573 struct uvc_camera_terminal_descriptor *cd; 574 int result, i; 575 char *pg = page; 576 577 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 578 579 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> 580 ci_parent; 581 opts = to_f_uvc_opts(opts_item); 582 cd = &opts->uvc_camera_terminal; 583 584 mutex_lock(&opts->lock); 585 for (result = 0, i = 0; i < cd->bControlSize; ++i) { 586 result += sprintf(pg, "%u\n", cd->bmControls[i]); 587 pg = page + result; 588 } 589 mutex_unlock(&opts->lock); 590 591 mutex_unlock(su_mutex); 592 return result; 593} 594 595UVC_ATTR(uvcg_default_camera_, bm_controls, bmControls); 596 597static struct configfs_attribute *uvcg_default_camera_attrs[] = { 598 &uvcg_default_camera_attr_b_terminal_id, 599 &uvcg_default_camera_attr_w_terminal_type, 600 &uvcg_default_camera_attr_b_assoc_terminal, 601 &uvcg_default_camera_attr_i_terminal, 602 &uvcg_default_camera_attr_w_objective_focal_length_min, 603 &uvcg_default_camera_attr_w_objective_focal_length_max, 604 &uvcg_default_camera_attr_w_ocular_focal_length, 605 &uvcg_default_camera_attr_bm_controls, 606 NULL, 607}; 608 609static const struct uvcg_config_group_type uvcg_default_camera_type = { 610 .type = { 611 .ct_item_ops = &uvcg_config_item_ops, 612 .ct_attrs = uvcg_default_camera_attrs, 613 .ct_owner = THIS_MODULE, 614 }, 615 .name = "default", 616}; 617 618/* ----------------------------------------------------------------------------- 619 * control/terminal/camera 620 */ 621 622static const struct uvcg_config_group_type uvcg_camera_grp_type = { 623 .type = { 624 .ct_item_ops = &uvcg_config_item_ops, 625 .ct_owner = THIS_MODULE, 626 }, 627 .name = "camera", 628 .children = (const struct uvcg_config_group_type*[]) { 629 &uvcg_default_camera_type, 630 NULL, 631 }, 632}; 633 634/* ----------------------------------------------------------------------------- 635 * control/terminal/output/default 636 */ 637 638#define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, bits) \ 639static ssize_t uvcg_default_output_##cname##_show( \ 640 struct config_item *item, char *page) \ 641{ \ 642 struct config_group *group = to_config_group(item); \ 643 struct f_uvc_opts *opts; \ 644 struct config_item *opts_item; \ 645 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ 646 struct uvc_output_terminal_descriptor *cd; \ 647 int result; \ 648 \ 649 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 650 \ 651 opts_item = group->cg_item.ci_parent->ci_parent-> \ 652 ci_parent->ci_parent; \ 653 opts = to_f_uvc_opts(opts_item); \ 654 cd = &opts->uvc_output_terminal; \ 655 \ 656 mutex_lock(&opts->lock); \ 657 result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \ 658 mutex_unlock(&opts->lock); \ 659 \ 660 mutex_unlock(su_mutex); \ 661 \ 662 return result; \ 663} \ 664 \ 665UVC_ATTR_RO(uvcg_default_output_, cname, aname) 666 667UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, 8); 668UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, 16); 669UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, 8); 670UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, 8); 671 672#undef UVCG_DEFAULT_OUTPUT_ATTR 673 674static ssize_t uvcg_default_output_b_source_id_show(struct config_item *item, 675 char *page) 676{ 677 struct config_group *group = to_config_group(item); 678 struct f_uvc_opts *opts; 679 struct config_item *opts_item; 680 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 681 struct uvc_output_terminal_descriptor *cd; 682 int result; 683 684 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 685 686 opts_item = group->cg_item.ci_parent->ci_parent-> 687 ci_parent->ci_parent; 688 opts = to_f_uvc_opts(opts_item); 689 cd = &opts->uvc_output_terminal; 690 691 mutex_lock(&opts->lock); 692 result = sprintf(page, "%u\n", le8_to_cpu(cd->bSourceID)); 693 mutex_unlock(&opts->lock); 694 695 mutex_unlock(su_mutex); 696 697 return result; 698} 699 700static ssize_t uvcg_default_output_b_source_id_store(struct config_item *item, 701 const char *page, size_t len) 702{ 703 struct config_group *group = to_config_group(item); 704 struct f_uvc_opts *opts; 705 struct config_item *opts_item; 706 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 707 struct uvc_output_terminal_descriptor *cd; 708 int result; 709 u8 num; 710 711 result = kstrtou8(page, 0, &num); 712 if (result) 713 return result; 714 715 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 716 717 opts_item = group->cg_item.ci_parent->ci_parent-> 718 ci_parent->ci_parent; 719 opts = to_f_uvc_opts(opts_item); 720 cd = &opts->uvc_output_terminal; 721 722 mutex_lock(&opts->lock); 723 cd->bSourceID = num; 724 mutex_unlock(&opts->lock); 725 726 mutex_unlock(su_mutex); 727 728 return len; 729} 730UVC_ATTR(uvcg_default_output_, b_source_id, bSourceID); 731 732static struct configfs_attribute *uvcg_default_output_attrs[] = { 733 &uvcg_default_output_attr_b_terminal_id, 734 &uvcg_default_output_attr_w_terminal_type, 735 &uvcg_default_output_attr_b_assoc_terminal, 736 &uvcg_default_output_attr_b_source_id, 737 &uvcg_default_output_attr_i_terminal, 738 NULL, 739}; 740 741static const struct uvcg_config_group_type uvcg_default_output_type = { 742 .type = { 743 .ct_item_ops = &uvcg_config_item_ops, 744 .ct_attrs = uvcg_default_output_attrs, 745 .ct_owner = THIS_MODULE, 746 }, 747 .name = "default", 748}; 749 750/* ----------------------------------------------------------------------------- 751 * control/terminal/output 752 */ 753 754static const struct uvcg_config_group_type uvcg_output_grp_type = { 755 .type = { 756 .ct_item_ops = &uvcg_config_item_ops, 757 .ct_owner = THIS_MODULE, 758 }, 759 .name = "output", 760 .children = (const struct uvcg_config_group_type*[]) { 761 &uvcg_default_output_type, 762 NULL, 763 }, 764}; 765 766/* ----------------------------------------------------------------------------- 767 * control/terminal 768 */ 769 770static const struct uvcg_config_group_type uvcg_terminal_grp_type = { 771 .type = { 772 .ct_item_ops = &uvcg_config_item_ops, 773 .ct_owner = THIS_MODULE, 774 }, 775 .name = "terminal", 776 .children = (const struct uvcg_config_group_type*[]) { 777 &uvcg_camera_grp_type, 778 &uvcg_output_grp_type, 779 NULL, 780 }, 781}; 782 783/* ----------------------------------------------------------------------------- 784 * control/extensions 785 */ 786 787#define UVCG_EXTENSION_ATTR(cname, aname, ro...) \ 788static ssize_t uvcg_extension_##cname##_show(struct config_item *item, \ 789 char *page) \ 790{ \ 791 struct config_group *group = to_config_group(item->ci_parent); \ 792 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ 793 struct uvcg_extension *xu = to_uvcg_extension(item); \ 794 struct config_item *opts_item; \ 795 struct f_uvc_opts *opts; \ 796 int ret; \ 797 \ 798 mutex_lock(su_mutex); \ 799 \ 800 opts_item = item->ci_parent->ci_parent->ci_parent; \ 801 opts = to_f_uvc_opts(opts_item); \ 802 \ 803 mutex_lock(&opts->lock); \ 804 ret = sprintf(page, "%u\n", xu->desc.aname); \ 805 mutex_unlock(&opts->lock); \ 806 \ 807 mutex_unlock(su_mutex); \ 808 \ 809 return ret; \ 810} \ 811UVC_ATTR##ro(uvcg_extension_, cname, aname) 812 813UVCG_EXTENSION_ATTR(b_length, bLength, _RO); 814UVCG_EXTENSION_ATTR(b_unit_id, bUnitID, _RO); 815UVCG_EXTENSION_ATTR(i_extension, iExtension, _RO); 816 817static ssize_t uvcg_extension_b_num_controls_store(struct config_item *item, 818 const char *page, size_t len) 819{ 820 struct config_group *group = to_config_group(item->ci_parent); 821 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 822 struct uvcg_extension *xu = to_uvcg_extension(item); 823 struct config_item *opts_item; 824 struct f_uvc_opts *opts; 825 int ret; 826 u8 num; 827 828 ret = kstrtou8(page, 0, &num); 829 if (ret) 830 return ret; 831 832 mutex_lock(su_mutex); 833 834 opts_item = item->ci_parent->ci_parent->ci_parent; 835 opts = to_f_uvc_opts(opts_item); 836 837 mutex_lock(&opts->lock); 838 xu->desc.bNumControls = num; 839 mutex_unlock(&opts->lock); 840 841 mutex_unlock(su_mutex); 842 843 return len; 844} 845UVCG_EXTENSION_ATTR(b_num_controls, bNumControls); 846 847/* 848 * In addition to storing bNrInPins, this function needs to realloc the 849 * memory for the baSourceID array and additionally expand bLength. 850 */ 851static ssize_t uvcg_extension_b_nr_in_pins_store(struct config_item *item, 852 const char *page, size_t len) 853{ 854 struct config_group *group = to_config_group(item->ci_parent); 855 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 856 struct uvcg_extension *xu = to_uvcg_extension(item); 857 struct config_item *opts_item; 858 struct f_uvc_opts *opts; 859 void *tmp_buf; 860 int ret; 861 u8 num; 862 863 ret = kstrtou8(page, 0, &num); 864 if (ret) 865 return ret; 866 867 mutex_lock(su_mutex); 868 869 opts_item = item->ci_parent->ci_parent->ci_parent; 870 opts = to_f_uvc_opts(opts_item); 871 872 mutex_lock(&opts->lock); 873 874 if (num == xu->desc.bNrInPins) { 875 ret = len; 876 goto unlock; 877 } 878 879 tmp_buf = krealloc_array(xu->desc.baSourceID, num, sizeof(u8), 880 GFP_KERNEL | __GFP_ZERO); 881 if (!tmp_buf) { 882 ret = -ENOMEM; 883 goto unlock; 884 } 885 886 xu->desc.baSourceID = tmp_buf; 887 xu->desc.bNrInPins = num; 888 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins, 889 xu->desc.bControlSize); 890 891 ret = len; 892 893unlock: 894 mutex_unlock(&opts->lock); 895 mutex_unlock(su_mutex); 896 return ret; 897} 898UVCG_EXTENSION_ATTR(b_nr_in_pins, bNrInPins); 899 900/* 901 * In addition to storing bControlSize, this function needs to realloc the 902 * memory for the bmControls array and additionally expand bLength. 903 */ 904static ssize_t uvcg_extension_b_control_size_store(struct config_item *item, 905 const char *page, size_t len) 906{ 907 struct config_group *group = to_config_group(item->ci_parent); 908 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 909 struct uvcg_extension *xu = to_uvcg_extension(item); 910 struct config_item *opts_item; 911 struct f_uvc_opts *opts; 912 void *tmp_buf; 913 int ret; 914 u8 num; 915 916 ret = kstrtou8(page, 0, &num); 917 if (ret) 918 return ret; 919 920 mutex_lock(su_mutex); 921 922 opts_item = item->ci_parent->ci_parent->ci_parent; 923 opts = to_f_uvc_opts(opts_item); 924 925 mutex_lock(&opts->lock); 926 927 if (num == xu->desc.bControlSize) { 928 ret = len; 929 goto unlock; 930 } 931 932 tmp_buf = krealloc_array(xu->desc.bmControls, num, sizeof(u8), 933 GFP_KERNEL | __GFP_ZERO); 934 if (!tmp_buf) { 935 ret = -ENOMEM; 936 goto unlock; 937 } 938 939 xu->desc.bmControls = tmp_buf; 940 xu->desc.bControlSize = num; 941 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins, 942 xu->desc.bControlSize); 943 944 ret = len; 945 946unlock: 947 mutex_unlock(&opts->lock); 948 mutex_unlock(su_mutex); 949 return ret; 950} 951 952UVCG_EXTENSION_ATTR(b_control_size, bControlSize); 953 954static ssize_t uvcg_extension_guid_extension_code_show(struct config_item *item, 955 char *page) 956{ 957 struct config_group *group = to_config_group(item->ci_parent); 958 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 959 struct uvcg_extension *xu = to_uvcg_extension(item); 960 struct config_item *opts_item; 961 struct f_uvc_opts *opts; 962 963 mutex_lock(su_mutex); 964 965 opts_item = item->ci_parent->ci_parent->ci_parent; 966 opts = to_f_uvc_opts(opts_item); 967 968 mutex_lock(&opts->lock); 969 memcpy(page, xu->desc.guidExtensionCode, sizeof(xu->desc.guidExtensionCode)); 970 mutex_unlock(&opts->lock); 971 972 mutex_unlock(su_mutex); 973 974 return sizeof(xu->desc.guidExtensionCode); 975} 976 977static ssize_t uvcg_extension_guid_extension_code_store(struct config_item *item, 978 const char *page, size_t len) 979{ 980 struct config_group *group = to_config_group(item->ci_parent); 981 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 982 struct uvcg_extension *xu = to_uvcg_extension(item); 983 struct config_item *opts_item; 984 struct f_uvc_opts *opts; 985 int ret; 986 987 mutex_lock(su_mutex); 988 989 opts_item = item->ci_parent->ci_parent->ci_parent; 990 opts = to_f_uvc_opts(opts_item); 991 992 mutex_lock(&opts->lock); 993 memcpy(xu->desc.guidExtensionCode, page, 994 min(sizeof(xu->desc.guidExtensionCode), len)); 995 mutex_unlock(&opts->lock); 996 997 mutex_unlock(su_mutex); 998 999 ret = sizeof(xu->desc.guidExtensionCode); 1000 1001 return ret; 1002} 1003 1004UVC_ATTR(uvcg_extension_, guid_extension_code, guidExtensionCode); 1005 1006static ssize_t uvcg_extension_ba_source_id_show(struct config_item *item, 1007 char *page) 1008{ 1009 struct config_group *group = to_config_group(item->ci_parent); 1010 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1011 struct uvcg_extension *xu = to_uvcg_extension(item); 1012 struct config_item *opts_item; 1013 struct f_uvc_opts *opts; 1014 char *pg = page; 1015 int ret, i; 1016 1017 mutex_lock(su_mutex); 1018 1019 opts_item = item->ci_parent->ci_parent->ci_parent; 1020 opts = to_f_uvc_opts(opts_item); 1021 1022 mutex_lock(&opts->lock); 1023 for (ret = 0, i = 0; i < xu->desc.bNrInPins; ++i) { 1024 ret += sprintf(pg, "%u\n", xu->desc.baSourceID[i]); 1025 pg = page + ret; 1026 } 1027 mutex_unlock(&opts->lock); 1028 1029 mutex_unlock(su_mutex); 1030 1031 return ret; 1032} 1033 1034static ssize_t uvcg_extension_ba_source_id_store(struct config_item *item, 1035 const char *page, size_t len) 1036{ 1037 struct config_group *group = to_config_group(item->ci_parent); 1038 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1039 struct uvcg_extension *xu = to_uvcg_extension(item); 1040 struct config_item *opts_item; 1041 struct f_uvc_opts *opts; 1042 u8 *source_ids, *iter; 1043 int ret, n = 0; 1044 1045 mutex_lock(su_mutex); 1046 1047 opts_item = item->ci_parent->ci_parent->ci_parent; 1048 opts = to_f_uvc_opts(opts_item); 1049 1050 mutex_lock(&opts->lock); 1051 1052 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, 1053 sizeof(u8)); 1054 if (ret) 1055 goto unlock; 1056 1057 iter = source_ids = kcalloc(n, sizeof(u8), GFP_KERNEL); 1058 if (!source_ids) { 1059 ret = -ENOMEM; 1060 goto unlock; 1061 } 1062 1063 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &iter, 1064 sizeof(u8)); 1065 if (ret) { 1066 kfree(source_ids); 1067 goto unlock; 1068 } 1069 1070 kfree(xu->desc.baSourceID); 1071 xu->desc.baSourceID = source_ids; 1072 xu->desc.bNrInPins = n; 1073 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins, 1074 xu->desc.bControlSize); 1075 1076 ret = len; 1077 1078unlock: 1079 mutex_unlock(&opts->lock); 1080 mutex_unlock(su_mutex); 1081 return ret; 1082} 1083UVC_ATTR(uvcg_extension_, ba_source_id, baSourceID); 1084 1085static ssize_t uvcg_extension_bm_controls_show(struct config_item *item, 1086 char *page) 1087{ 1088 struct config_group *group = to_config_group(item->ci_parent); 1089 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1090 struct uvcg_extension *xu = to_uvcg_extension(item); 1091 struct config_item *opts_item; 1092 struct f_uvc_opts *opts; 1093 char *pg = page; 1094 int ret, i; 1095 1096 mutex_lock(su_mutex); 1097 1098 opts_item = item->ci_parent->ci_parent->ci_parent; 1099 opts = to_f_uvc_opts(opts_item); 1100 1101 mutex_lock(&opts->lock); 1102 for (ret = 0, i = 0; i < xu->desc.bControlSize; ++i) { 1103 ret += sprintf(pg, "0x%02x\n", xu->desc.bmControls[i]); 1104 pg = page + ret; 1105 } 1106 mutex_unlock(&opts->lock); 1107 1108 mutex_unlock(su_mutex); 1109 1110 return ret; 1111} 1112 1113static ssize_t uvcg_extension_bm_controls_store(struct config_item *item, 1114 const char *page, size_t len) 1115{ 1116 struct config_group *group = to_config_group(item->ci_parent); 1117 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1118 struct uvcg_extension *xu = to_uvcg_extension(item); 1119 struct config_item *opts_item; 1120 struct f_uvc_opts *opts; 1121 u8 *bm_controls, *iter; 1122 int ret, n = 0; 1123 1124 mutex_lock(su_mutex); 1125 1126 opts_item = item->ci_parent->ci_parent->ci_parent; 1127 opts = to_f_uvc_opts(opts_item); 1128 1129 mutex_lock(&opts->lock); 1130 1131 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, 1132 sizeof(u8)); 1133 if (ret) 1134 goto unlock; 1135 1136 iter = bm_controls = kcalloc(n, sizeof(u8), GFP_KERNEL); 1137 if (!bm_controls) { 1138 ret = -ENOMEM; 1139 goto unlock; 1140 } 1141 1142 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &iter, 1143 sizeof(u8)); 1144 if (ret) { 1145 kfree(bm_controls); 1146 goto unlock; 1147 } 1148 1149 kfree(xu->desc.bmControls); 1150 xu->desc.bmControls = bm_controls; 1151 xu->desc.bControlSize = n; 1152 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(xu->desc.bNrInPins, 1153 xu->desc.bControlSize); 1154 1155 ret = len; 1156 1157unlock: 1158 mutex_unlock(&opts->lock); 1159 mutex_unlock(su_mutex); 1160 return ret; 1161} 1162 1163UVC_ATTR(uvcg_extension_, bm_controls, bmControls); 1164 1165static struct configfs_attribute *uvcg_extension_attrs[] = { 1166 &uvcg_extension_attr_b_length, 1167 &uvcg_extension_attr_b_unit_id, 1168 &uvcg_extension_attr_b_num_controls, 1169 &uvcg_extension_attr_b_nr_in_pins, 1170 &uvcg_extension_attr_b_control_size, 1171 &uvcg_extension_attr_guid_extension_code, 1172 &uvcg_extension_attr_ba_source_id, 1173 &uvcg_extension_attr_bm_controls, 1174 &uvcg_extension_attr_i_extension, 1175 NULL, 1176}; 1177 1178static void uvcg_extension_release(struct config_item *item) 1179{ 1180 struct uvcg_extension *xu = container_of(item, struct uvcg_extension, item); 1181 1182 kfree(xu); 1183} 1184 1185static int uvcg_extension_allow_link(struct config_item *src, struct config_item *tgt) 1186{ 1187 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1188 struct uvcg_extension *xu = to_uvcg_extension(src); 1189 struct config_item *gadget_item; 1190 struct gadget_string *string; 1191 struct config_item *strings; 1192 int ret = 0; 1193 1194 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1195 1196 /* Validate that the target of the link is an entry in strings/<langid> */ 1197 gadget_item = src->ci_parent->ci_parent->ci_parent->ci_parent->ci_parent; 1198 strings = config_group_find_item(to_config_group(gadget_item), "strings"); 1199 if (!strings || tgt->ci_parent->ci_parent != strings) { 1200 ret = -EINVAL; 1201 goto put_strings; 1202 } 1203 1204 string = to_gadget_string(tgt); 1205 xu->string_descriptor_index = string->usb_string.id; 1206 1207put_strings: 1208 config_item_put(strings); 1209 mutex_unlock(su_mutex); 1210 1211 return ret; 1212} 1213 1214static void uvcg_extension_drop_link(struct config_item *src, struct config_item *tgt) 1215{ 1216 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1217 struct uvcg_extension *xu = to_uvcg_extension(src); 1218 struct config_item *opts_item; 1219 struct f_uvc_opts *opts; 1220 1221 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1222 1223 opts_item = src->ci_parent->ci_parent->ci_parent; 1224 opts = to_f_uvc_opts(opts_item); 1225 1226 mutex_lock(&opts->lock); 1227 1228 xu->string_descriptor_index = 0; 1229 1230 mutex_unlock(&opts->lock); 1231 1232 mutex_unlock(su_mutex); 1233} 1234 1235static struct configfs_item_operations uvcg_extension_item_ops = { 1236 .release = uvcg_extension_release, 1237 .allow_link = uvcg_extension_allow_link, 1238 .drop_link = uvcg_extension_drop_link, 1239}; 1240 1241static const struct config_item_type uvcg_extension_type = { 1242 .ct_item_ops = &uvcg_extension_item_ops, 1243 .ct_attrs = uvcg_extension_attrs, 1244 .ct_owner = THIS_MODULE, 1245}; 1246 1247static void uvcg_extension_drop(struct config_group *group, struct config_item *item) 1248{ 1249 struct uvcg_extension *xu = container_of(item, struct uvcg_extension, item); 1250 struct config_item *opts_item; 1251 struct f_uvc_opts *opts; 1252 1253 opts_item = group->cg_item.ci_parent->ci_parent; 1254 opts = to_f_uvc_opts(opts_item); 1255 1256 mutex_lock(&opts->lock); 1257 1258 config_item_put(item); 1259 list_del(&xu->list); 1260 kfree(xu->desc.baSourceID); 1261 kfree(xu->desc.bmControls); 1262 1263 mutex_unlock(&opts->lock); 1264} 1265 1266static struct config_item *uvcg_extension_make(struct config_group *group, const char *name) 1267{ 1268 struct config_item *opts_item; 1269 struct uvcg_extension *xu; 1270 struct f_uvc_opts *opts; 1271 1272 opts_item = group->cg_item.ci_parent->ci_parent; 1273 opts = to_f_uvc_opts(opts_item); 1274 1275 xu = kzalloc(sizeof(*xu), GFP_KERNEL); 1276 if (!xu) 1277 return ERR_PTR(-ENOMEM); 1278 1279 xu->desc.bLength = UVC_DT_EXTENSION_UNIT_SIZE(0, 0); 1280 xu->desc.bDescriptorType = USB_DT_CS_INTERFACE; 1281 xu->desc.bDescriptorSubType = UVC_VC_EXTENSION_UNIT; 1282 xu->desc.bNumControls = 0; 1283 xu->desc.bNrInPins = 0; 1284 xu->desc.baSourceID = NULL; 1285 xu->desc.bControlSize = 0; 1286 xu->desc.bmControls = NULL; 1287 1288 mutex_lock(&opts->lock); 1289 1290 xu->desc.bUnitID = ++opts->last_unit_id; 1291 1292 config_item_init_type_name(&xu->item, name, &uvcg_extension_type); 1293 list_add_tail(&xu->list, &opts->extension_units); 1294 1295 mutex_unlock(&opts->lock); 1296 1297 return &xu->item; 1298} 1299 1300static struct configfs_group_operations uvcg_extensions_grp_ops = { 1301 .make_item = uvcg_extension_make, 1302 .drop_item = uvcg_extension_drop, 1303}; 1304 1305static const struct uvcg_config_group_type uvcg_extensions_grp_type = { 1306 .type = { 1307 .ct_item_ops = &uvcg_config_item_ops, 1308 .ct_group_ops = &uvcg_extensions_grp_ops, 1309 .ct_owner = THIS_MODULE, 1310 }, 1311 .name = "extensions", 1312}; 1313 1314/* ----------------------------------------------------------------------------- 1315 * control/class/{fs|ss} 1316 */ 1317 1318struct uvcg_control_class_group { 1319 struct config_group group; 1320 const char *name; 1321}; 1322 1323static inline struct uvc_descriptor_header 1324**uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o) 1325{ 1326 struct uvcg_control_class_group *group = 1327 container_of(i, struct uvcg_control_class_group, 1328 group.cg_item); 1329 1330 if (!strcmp(group->name, "fs")) 1331 return o->uvc_fs_control_cls; 1332 1333 if (!strcmp(group->name, "ss")) 1334 return o->uvc_ss_control_cls; 1335 1336 return NULL; 1337} 1338 1339static int uvcg_control_class_allow_link(struct config_item *src, 1340 struct config_item *target) 1341{ 1342 struct config_item *control, *header; 1343 struct f_uvc_opts *opts; 1344 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1345 struct uvc_descriptor_header **class_array; 1346 struct uvcg_control_header *target_hdr; 1347 int ret = -EINVAL; 1348 1349 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1350 1351 control = src->ci_parent->ci_parent; 1352 header = config_group_find_item(to_config_group(control), "header"); 1353 if (!header || target->ci_parent != header) 1354 goto out; 1355 1356 opts = to_f_uvc_opts(control->ci_parent); 1357 1358 mutex_lock(&opts->lock); 1359 1360 class_array = uvcg_get_ctl_class_arr(src, opts); 1361 if (!class_array) 1362 goto unlock; 1363 if (opts->refcnt || class_array[0]) { 1364 ret = -EBUSY; 1365 goto unlock; 1366 } 1367 1368 target_hdr = to_uvcg_control_header(target); 1369 ++target_hdr->linked; 1370 class_array[0] = (struct uvc_descriptor_header *)&target_hdr->desc; 1371 ret = 0; 1372 1373unlock: 1374 mutex_unlock(&opts->lock); 1375out: 1376 config_item_put(header); 1377 mutex_unlock(su_mutex); 1378 return ret; 1379} 1380 1381static void uvcg_control_class_drop_link(struct config_item *src, 1382 struct config_item *target) 1383{ 1384 struct config_item *control, *header; 1385 struct f_uvc_opts *opts; 1386 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1387 struct uvc_descriptor_header **class_array; 1388 struct uvcg_control_header *target_hdr; 1389 1390 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1391 1392 control = src->ci_parent->ci_parent; 1393 header = config_group_find_item(to_config_group(control), "header"); 1394 if (!header || target->ci_parent != header) 1395 goto out; 1396 1397 opts = to_f_uvc_opts(control->ci_parent); 1398 1399 mutex_lock(&opts->lock); 1400 1401 class_array = uvcg_get_ctl_class_arr(src, opts); 1402 if (!class_array || opts->refcnt) 1403 goto unlock; 1404 1405 target_hdr = to_uvcg_control_header(target); 1406 --target_hdr->linked; 1407 class_array[0] = NULL; 1408 1409unlock: 1410 mutex_unlock(&opts->lock); 1411out: 1412 config_item_put(header); 1413 mutex_unlock(su_mutex); 1414} 1415 1416static struct configfs_item_operations uvcg_control_class_item_ops = { 1417 .release = uvcg_config_item_release, 1418 .allow_link = uvcg_control_class_allow_link, 1419 .drop_link = uvcg_control_class_drop_link, 1420}; 1421 1422static const struct config_item_type uvcg_control_class_type = { 1423 .ct_item_ops = &uvcg_control_class_item_ops, 1424 .ct_owner = THIS_MODULE, 1425}; 1426 1427/* ----------------------------------------------------------------------------- 1428 * control/class 1429 */ 1430 1431static int uvcg_control_class_create_children(struct config_group *parent) 1432{ 1433 static const char * const names[] = { "fs", "ss" }; 1434 unsigned int i; 1435 1436 for (i = 0; i < ARRAY_SIZE(names); ++i) { 1437 struct uvcg_control_class_group *group; 1438 1439 group = kzalloc(sizeof(*group), GFP_KERNEL); 1440 if (!group) 1441 return -ENOMEM; 1442 1443 group->name = names[i]; 1444 1445 config_group_init_type_name(&group->group, group->name, 1446 &uvcg_control_class_type); 1447 configfs_add_default_group(&group->group, parent); 1448 } 1449 1450 return 0; 1451} 1452 1453static const struct uvcg_config_group_type uvcg_control_class_grp_type = { 1454 .type = { 1455 .ct_item_ops = &uvcg_config_item_ops, 1456 .ct_owner = THIS_MODULE, 1457 }, 1458 .name = "class", 1459 .create_children = uvcg_control_class_create_children, 1460}; 1461 1462/* ----------------------------------------------------------------------------- 1463 * control 1464 */ 1465 1466static ssize_t uvcg_default_control_b_interface_number_show( 1467 struct config_item *item, char *page) 1468{ 1469 struct config_group *group = to_config_group(item); 1470 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1471 struct config_item *opts_item; 1472 struct f_uvc_opts *opts; 1473 int result = 0; 1474 1475 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1476 1477 opts_item = item->ci_parent; 1478 opts = to_f_uvc_opts(opts_item); 1479 1480 mutex_lock(&opts->lock); 1481 result += sprintf(page, "%u\n", opts->control_interface); 1482 mutex_unlock(&opts->lock); 1483 1484 mutex_unlock(su_mutex); 1485 1486 return result; 1487} 1488 1489UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber); 1490 1491static ssize_t uvcg_default_control_enable_interrupt_ep_show( 1492 struct config_item *item, char *page) 1493{ 1494 struct config_group *group = to_config_group(item); 1495 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1496 struct config_item *opts_item; 1497 struct f_uvc_opts *opts; 1498 int result = 0; 1499 1500 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1501 1502 opts_item = item->ci_parent; 1503 opts = to_f_uvc_opts(opts_item); 1504 1505 mutex_lock(&opts->lock); 1506 result += sprintf(page, "%u\n", opts->enable_interrupt_ep); 1507 mutex_unlock(&opts->lock); 1508 1509 mutex_unlock(su_mutex); 1510 1511 return result; 1512} 1513 1514static ssize_t uvcg_default_control_enable_interrupt_ep_store( 1515 struct config_item *item, const char *page, size_t len) 1516{ 1517 struct config_group *group = to_config_group(item); 1518 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 1519 struct config_item *opts_item; 1520 struct f_uvc_opts *opts; 1521 ssize_t ret; 1522 u8 num; 1523 1524 ret = kstrtou8(page, 0, &num); 1525 if (ret) 1526 return ret; 1527 1528 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1529 1530 opts_item = item->ci_parent; 1531 opts = to_f_uvc_opts(opts_item); 1532 1533 mutex_lock(&opts->lock); 1534 opts->enable_interrupt_ep = num; 1535 mutex_unlock(&opts->lock); 1536 1537 mutex_unlock(su_mutex); 1538 1539 return len; 1540} 1541UVC_ATTR(uvcg_default_control_, enable_interrupt_ep, enable_interrupt_ep); 1542 1543static struct configfs_attribute *uvcg_default_control_attrs[] = { 1544 &uvcg_default_control_attr_b_interface_number, 1545 &uvcg_default_control_attr_enable_interrupt_ep, 1546 NULL, 1547}; 1548 1549static const struct uvcg_config_group_type uvcg_control_grp_type = { 1550 .type = { 1551 .ct_item_ops = &uvcg_config_item_ops, 1552 .ct_attrs = uvcg_default_control_attrs, 1553 .ct_owner = THIS_MODULE, 1554 }, 1555 .name = "control", 1556 .children = (const struct uvcg_config_group_type*[]) { 1557 &uvcg_control_header_grp_type, 1558 &uvcg_processing_grp_type, 1559 &uvcg_terminal_grp_type, 1560 &uvcg_control_class_grp_type, 1561 &uvcg_extensions_grp_type, 1562 NULL, 1563 }, 1564}; 1565 1566/* ----------------------------------------------------------------------------- 1567 * streaming/uncompressed 1568 * streaming/mjpeg 1569 */ 1570 1571static const char * const uvcg_format_names[] = { 1572 "uncompressed", 1573 "mjpeg", 1574}; 1575 1576static struct uvcg_color_matching * 1577uvcg_format_get_default_color_match(struct config_item *streaming) 1578{ 1579 struct config_item *color_matching_item, *cm_default; 1580 struct uvcg_color_matching *color_match; 1581 1582 color_matching_item = config_group_find_item(to_config_group(streaming), 1583 "color_matching"); 1584 if (!color_matching_item) 1585 return NULL; 1586 1587 cm_default = config_group_find_item(to_config_group(color_matching_item), 1588 "default"); 1589 config_item_put(color_matching_item); 1590 if (!cm_default) 1591 return NULL; 1592 1593 color_match = to_uvcg_color_matching(to_config_group(cm_default)); 1594 config_item_put(cm_default); 1595 1596 return color_match; 1597} 1598 1599static int uvcg_format_allow_link(struct config_item *src, struct config_item *tgt) 1600{ 1601 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1602 struct uvcg_color_matching *color_matching_desc; 1603 struct config_item *streaming, *color_matching; 1604 struct uvcg_format *fmt; 1605 int ret = 0; 1606 1607 mutex_lock(su_mutex); 1608 1609 streaming = src->ci_parent->ci_parent; 1610 color_matching = config_group_find_item(to_config_group(streaming), "color_matching"); 1611 if (!color_matching || color_matching != tgt->ci_parent) { 1612 ret = -EINVAL; 1613 goto out_put_cm; 1614 } 1615 1616 fmt = to_uvcg_format(src); 1617 1618 /* 1619 * There's always a color matching descriptor associated with the format 1620 * but without a symlink it should only ever be the default one. If it's 1621 * not the default, there's already a symlink and we should bail out. 1622 */ 1623 color_matching_desc = uvcg_format_get_default_color_match(streaming); 1624 if (fmt->color_matching != color_matching_desc) { 1625 ret = -EBUSY; 1626 goto out_put_cm; 1627 } 1628 1629 color_matching_desc->refcnt--; 1630 1631 color_matching_desc = to_uvcg_color_matching(to_config_group(tgt)); 1632 fmt->color_matching = color_matching_desc; 1633 color_matching_desc->refcnt++; 1634 1635out_put_cm: 1636 config_item_put(color_matching); 1637 mutex_unlock(su_mutex); 1638 1639 return ret; 1640} 1641 1642static void uvcg_format_drop_link(struct config_item *src, struct config_item *tgt) 1643{ 1644 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1645 struct uvcg_color_matching *color_matching_desc; 1646 struct config_item *streaming; 1647 struct uvcg_format *fmt; 1648 1649 mutex_lock(su_mutex); 1650 1651 color_matching_desc = to_uvcg_color_matching(to_config_group(tgt)); 1652 color_matching_desc->refcnt--; 1653 1654 streaming = src->ci_parent->ci_parent; 1655 color_matching_desc = uvcg_format_get_default_color_match(streaming); 1656 1657 fmt = to_uvcg_format(src); 1658 fmt->color_matching = color_matching_desc; 1659 color_matching_desc->refcnt++; 1660 1661 mutex_unlock(su_mutex); 1662} 1663 1664static struct configfs_item_operations uvcg_format_item_operations = { 1665 .release = uvcg_config_item_release, 1666 .allow_link = uvcg_format_allow_link, 1667 .drop_link = uvcg_format_drop_link, 1668}; 1669 1670static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page) 1671{ 1672 struct f_uvc_opts *opts; 1673 struct config_item *opts_item; 1674 struct mutex *su_mutex = &f->group.cg_subsys->su_mutex; 1675 int result, i; 1676 char *pg = page; 1677 1678 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1679 1680 opts_item = f->group.cg_item.ci_parent->ci_parent->ci_parent; 1681 opts = to_f_uvc_opts(opts_item); 1682 1683 mutex_lock(&opts->lock); 1684 result = sprintf(pg, "0x"); 1685 pg += result; 1686 for (i = 0; i < UVCG_STREAMING_CONTROL_SIZE; ++i) { 1687 result += sprintf(pg, "%x\n", f->bmaControls[i]); 1688 pg = page + result; 1689 } 1690 mutex_unlock(&opts->lock); 1691 1692 mutex_unlock(su_mutex); 1693 return result; 1694} 1695 1696static ssize_t uvcg_format_bma_controls_store(struct uvcg_format *ch, 1697 const char *page, size_t len) 1698{ 1699 struct f_uvc_opts *opts; 1700 struct config_item *opts_item; 1701 struct mutex *su_mutex = &ch->group.cg_subsys->su_mutex; 1702 int ret = -EINVAL; 1703 1704 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1705 1706 opts_item = ch->group.cg_item.ci_parent->ci_parent->ci_parent; 1707 opts = to_f_uvc_opts(opts_item); 1708 1709 mutex_lock(&opts->lock); 1710 if (ch->linked || opts->refcnt) { 1711 ret = -EBUSY; 1712 goto end; 1713 } 1714 1715 if (len < 4 || *page != '0' || 1716 (*(page + 1) != 'x' && *(page + 1) != 'X')) 1717 goto end; 1718 ret = hex2bin(ch->bmaControls, page + 2, 1); 1719 if (ret < 0) 1720 goto end; 1721 ret = len; 1722end: 1723 mutex_unlock(&opts->lock); 1724 mutex_unlock(su_mutex); 1725 return ret; 1726} 1727 1728/* ----------------------------------------------------------------------------- 1729 * streaming/header/<NAME> 1730 * streaming/header 1731 */ 1732 1733static void uvcg_format_set_indices(struct config_group *fmt); 1734 1735static int uvcg_streaming_header_allow_link(struct config_item *src, 1736 struct config_item *target) 1737{ 1738 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1739 struct config_item *opts_item; 1740 struct f_uvc_opts *opts; 1741 struct uvcg_streaming_header *src_hdr; 1742 struct uvcg_format *target_fmt = NULL; 1743 struct uvcg_format_ptr *format_ptr; 1744 int i, ret = -EINVAL; 1745 1746 src_hdr = to_uvcg_streaming_header(src); 1747 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1748 1749 opts_item = src->ci_parent->ci_parent->ci_parent; 1750 opts = to_f_uvc_opts(opts_item); 1751 1752 mutex_lock(&opts->lock); 1753 1754 if (src_hdr->linked) { 1755 ret = -EBUSY; 1756 goto out; 1757 } 1758 1759 /* 1760 * Linking is only allowed to direct children of the format nodes 1761 * (streaming/uncompressed or streaming/mjpeg nodes). First check that 1762 * the grand-parent of the target matches the grand-parent of the source 1763 * (the streaming node), and then verify that the target parent is a 1764 * format node. 1765 */ 1766 if (src->ci_parent->ci_parent != target->ci_parent->ci_parent) 1767 goto out; 1768 1769 for (i = 0; i < ARRAY_SIZE(uvcg_format_names); ++i) { 1770 if (!strcmp(target->ci_parent->ci_name, uvcg_format_names[i])) 1771 break; 1772 } 1773 1774 if (i == ARRAY_SIZE(uvcg_format_names)) 1775 goto out; 1776 1777 target_fmt = container_of(to_config_group(target), struct uvcg_format, 1778 group); 1779 1780 uvcg_format_set_indices(to_config_group(target)); 1781 1782 format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL); 1783 if (!format_ptr) { 1784 ret = -ENOMEM; 1785 goto out; 1786 } 1787 ret = 0; 1788 format_ptr->fmt = target_fmt; 1789 list_add_tail(&format_ptr->entry, &src_hdr->formats); 1790 ++src_hdr->num_fmt; 1791 ++target_fmt->linked; 1792 1793out: 1794 mutex_unlock(&opts->lock); 1795 mutex_unlock(su_mutex); 1796 return ret; 1797} 1798 1799static void uvcg_streaming_header_drop_link(struct config_item *src, 1800 struct config_item *target) 1801{ 1802 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 1803 struct config_item *opts_item; 1804 struct f_uvc_opts *opts; 1805 struct uvcg_streaming_header *src_hdr; 1806 struct uvcg_format *target_fmt = NULL; 1807 struct uvcg_format_ptr *format_ptr, *tmp; 1808 1809 src_hdr = to_uvcg_streaming_header(src); 1810 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1811 1812 opts_item = src->ci_parent->ci_parent->ci_parent; 1813 opts = to_f_uvc_opts(opts_item); 1814 1815 mutex_lock(&opts->lock); 1816 target_fmt = container_of(to_config_group(target), struct uvcg_format, 1817 group); 1818 1819 list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry) 1820 if (format_ptr->fmt == target_fmt) { 1821 list_del(&format_ptr->entry); 1822 kfree(format_ptr); 1823 --src_hdr->num_fmt; 1824 break; 1825 } 1826 1827 --target_fmt->linked; 1828 1829 mutex_unlock(&opts->lock); 1830 mutex_unlock(su_mutex); 1831} 1832 1833static struct configfs_item_operations uvcg_streaming_header_item_ops = { 1834 .release = uvcg_config_item_release, 1835 .allow_link = uvcg_streaming_header_allow_link, 1836 .drop_link = uvcg_streaming_header_drop_link, 1837}; 1838 1839#define UVCG_STREAMING_HEADER_ATTR(cname, aname, bits) \ 1840static ssize_t uvcg_streaming_header_##cname##_show( \ 1841 struct config_item *item, char *page) \ 1842{ \ 1843 struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \ 1844 struct f_uvc_opts *opts; \ 1845 struct config_item *opts_item; \ 1846 struct mutex *su_mutex = &sh->item.ci_group->cg_subsys->su_mutex;\ 1847 int result; \ 1848 \ 1849 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1850 \ 1851 opts_item = sh->item.ci_parent->ci_parent->ci_parent; \ 1852 opts = to_f_uvc_opts(opts_item); \ 1853 \ 1854 mutex_lock(&opts->lock); \ 1855 result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\ 1856 mutex_unlock(&opts->lock); \ 1857 \ 1858 mutex_unlock(su_mutex); \ 1859 return result; \ 1860} \ 1861 \ 1862UVC_ATTR_RO(uvcg_streaming_header_, cname, aname) 1863 1864UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, 8); 1865UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, 8); 1866UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, 8); 1867UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, 8); 1868UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, 8); 1869 1870#undef UVCG_STREAMING_HEADER_ATTR 1871 1872static struct configfs_attribute *uvcg_streaming_header_attrs[] = { 1873 &uvcg_streaming_header_attr_bm_info, 1874 &uvcg_streaming_header_attr_b_terminal_link, 1875 &uvcg_streaming_header_attr_b_still_capture_method, 1876 &uvcg_streaming_header_attr_b_trigger_support, 1877 &uvcg_streaming_header_attr_b_trigger_usage, 1878 NULL, 1879}; 1880 1881static const struct config_item_type uvcg_streaming_header_type = { 1882 .ct_item_ops = &uvcg_streaming_header_item_ops, 1883 .ct_attrs = uvcg_streaming_header_attrs, 1884 .ct_owner = THIS_MODULE, 1885}; 1886 1887static struct config_item 1888*uvcg_streaming_header_make(struct config_group *group, const char *name) 1889{ 1890 struct uvcg_streaming_header *h; 1891 1892 h = kzalloc(sizeof(*h), GFP_KERNEL); 1893 if (!h) 1894 return ERR_PTR(-ENOMEM); 1895 1896 INIT_LIST_HEAD(&h->formats); 1897 h->desc.bDescriptorType = USB_DT_CS_INTERFACE; 1898 h->desc.bDescriptorSubType = UVC_VS_INPUT_HEADER; 1899 h->desc.bTerminalLink = 3; 1900 h->desc.bControlSize = UVCG_STREAMING_CONTROL_SIZE; 1901 1902 config_item_init_type_name(&h->item, name, &uvcg_streaming_header_type); 1903 1904 return &h->item; 1905} 1906 1907static struct configfs_group_operations uvcg_streaming_header_grp_ops = { 1908 .make_item = uvcg_streaming_header_make, 1909}; 1910 1911static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = { 1912 .type = { 1913 .ct_item_ops = &uvcg_config_item_ops, 1914 .ct_group_ops = &uvcg_streaming_header_grp_ops, 1915 .ct_owner = THIS_MODULE, 1916 }, 1917 .name = "header", 1918}; 1919 1920/* ----------------------------------------------------------------------------- 1921 * streaming/<mode>/<format>/<NAME> 1922 */ 1923 1924#define UVCG_FRAME_ATTR(cname, aname, bits) \ 1925static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\ 1926{ \ 1927 struct uvcg_frame *f = to_uvcg_frame(item); \ 1928 struct f_uvc_opts *opts; \ 1929 struct config_item *opts_item; \ 1930 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\ 1931 int result; \ 1932 \ 1933 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1934 \ 1935 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \ 1936 opts = to_f_uvc_opts(opts_item); \ 1937 \ 1938 mutex_lock(&opts->lock); \ 1939 result = sprintf(page, "%u\n", f->frame.cname); \ 1940 mutex_unlock(&opts->lock); \ 1941 \ 1942 mutex_unlock(su_mutex); \ 1943 return result; \ 1944} \ 1945 \ 1946static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \ 1947 const char *page, size_t len)\ 1948{ \ 1949 struct uvcg_frame *f = to_uvcg_frame(item); \ 1950 struct f_uvc_opts *opts; \ 1951 struct config_item *opts_item; \ 1952 struct uvcg_format *fmt; \ 1953 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\ 1954 typeof(f->frame.cname) num; \ 1955 int ret; \ 1956 \ 1957 ret = kstrtou##bits(page, 0, &num); \ 1958 if (ret) \ 1959 return ret; \ 1960 \ 1961 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 1962 \ 1963 opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \ 1964 opts = to_f_uvc_opts(opts_item); \ 1965 fmt = to_uvcg_format(f->item.ci_parent); \ 1966 \ 1967 mutex_lock(&opts->lock); \ 1968 if (fmt->linked || opts->refcnt) { \ 1969 ret = -EBUSY; \ 1970 goto end; \ 1971 } \ 1972 \ 1973 f->frame.cname = num; \ 1974 ret = len; \ 1975end: \ 1976 mutex_unlock(&opts->lock); \ 1977 mutex_unlock(su_mutex); \ 1978 return ret; \ 1979} \ 1980 \ 1981UVC_ATTR(uvcg_frame_, cname, aname); 1982 1983static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item, 1984 char *page) 1985{ 1986 struct uvcg_frame *f = to_uvcg_frame(item); 1987 struct uvcg_format *fmt; 1988 struct f_uvc_opts *opts; 1989 struct config_item *opts_item; 1990 struct config_item *fmt_item; 1991 struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex; 1992 int result; 1993 1994 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 1995 1996 fmt_item = f->item.ci_parent; 1997 fmt = to_uvcg_format(fmt_item); 1998 1999 if (!fmt->linked) { 2000 result = -EBUSY; 2001 goto out; 2002 } 2003 2004 opts_item = fmt_item->ci_parent->ci_parent->ci_parent; 2005 opts = to_f_uvc_opts(opts_item); 2006 2007 mutex_lock(&opts->lock); 2008 result = sprintf(page, "%u\n", f->frame.b_frame_index); 2009 mutex_unlock(&opts->lock); 2010 2011out: 2012 mutex_unlock(su_mutex); 2013 return result; 2014} 2015 2016UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex); 2017 2018UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8); 2019UVCG_FRAME_ATTR(w_width, wWidth, 16); 2020UVCG_FRAME_ATTR(w_height, wHeight, 16); 2021UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32); 2022UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32); 2023UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32); 2024UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32); 2025 2026#undef UVCG_FRAME_ATTR 2027 2028static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item, 2029 char *page) 2030{ 2031 struct uvcg_frame *frm = to_uvcg_frame(item); 2032 struct f_uvc_opts *opts; 2033 struct config_item *opts_item; 2034 struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex; 2035 int result, i; 2036 char *pg = page; 2037 2038 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 2039 2040 opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent; 2041 opts = to_f_uvc_opts(opts_item); 2042 2043 mutex_lock(&opts->lock); 2044 for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) { 2045 result += sprintf(pg, "%u\n", frm->dw_frame_interval[i]); 2046 pg = page + result; 2047 } 2048 mutex_unlock(&opts->lock); 2049 2050 mutex_unlock(su_mutex); 2051 return result; 2052} 2053 2054static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item, 2055 const char *page, size_t len) 2056{ 2057 struct uvcg_frame *ch = to_uvcg_frame(item); 2058 struct f_uvc_opts *opts; 2059 struct config_item *opts_item; 2060 struct uvcg_format *fmt; 2061 struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex; 2062 int ret = 0, n = 0; 2063 u32 *frm_intrv, *tmp; 2064 2065 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 2066 2067 opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent; 2068 opts = to_f_uvc_opts(opts_item); 2069 fmt = to_uvcg_format(ch->item.ci_parent); 2070 2071 mutex_lock(&opts->lock); 2072 if (fmt->linked || opts->refcnt) { 2073 ret = -EBUSY; 2074 goto end; 2075 } 2076 2077 ret = __uvcg_iter_item_entries(page, len, __uvcg_count_item_entries, &n, sizeof(u32)); 2078 if (ret) 2079 goto end; 2080 2081 tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL); 2082 if (!frm_intrv) { 2083 ret = -ENOMEM; 2084 goto end; 2085 } 2086 2087 ret = __uvcg_iter_item_entries(page, len, __uvcg_fill_item_entries, &tmp, sizeof(u32)); 2088 if (ret) { 2089 kfree(frm_intrv); 2090 goto end; 2091 } 2092 2093 kfree(ch->dw_frame_interval); 2094 ch->dw_frame_interval = frm_intrv; 2095 ch->frame.b_frame_interval_type = n; 2096 sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval), 2097 uvcg_config_compare_u32, NULL); 2098 ret = len; 2099 2100end: 2101 mutex_unlock(&opts->lock); 2102 mutex_unlock(su_mutex); 2103 return ret; 2104} 2105 2106UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval); 2107 2108static struct configfs_attribute *uvcg_frame_attrs[] = { 2109 &uvcg_frame_attr_b_frame_index, 2110 &uvcg_frame_attr_bm_capabilities, 2111 &uvcg_frame_attr_w_width, 2112 &uvcg_frame_attr_w_height, 2113 &uvcg_frame_attr_dw_min_bit_rate, 2114 &uvcg_frame_attr_dw_max_bit_rate, 2115 &uvcg_frame_attr_dw_max_video_frame_buffer_size, 2116 &uvcg_frame_attr_dw_default_frame_interval, 2117 &uvcg_frame_attr_dw_frame_interval, 2118 NULL, 2119}; 2120 2121static const struct config_item_type uvcg_frame_type = { 2122 .ct_item_ops = &uvcg_config_item_ops, 2123 .ct_attrs = uvcg_frame_attrs, 2124 .ct_owner = THIS_MODULE, 2125}; 2126 2127static struct config_item *uvcg_frame_make(struct config_group *group, 2128 const char *name) 2129{ 2130 struct uvcg_frame *h; 2131 struct uvcg_format *fmt; 2132 struct f_uvc_opts *opts; 2133 struct config_item *opts_item; 2134 struct uvcg_frame_ptr *frame_ptr; 2135 2136 h = kzalloc(sizeof(*h), GFP_KERNEL); 2137 if (!h) 2138 return ERR_PTR(-ENOMEM); 2139 2140 h->frame.b_descriptor_type = USB_DT_CS_INTERFACE; 2141 h->frame.b_frame_index = 1; 2142 h->frame.w_width = 640; 2143 h->frame.w_height = 360; 2144 h->frame.dw_min_bit_rate = 18432000; 2145 h->frame.dw_max_bit_rate = 55296000; 2146 h->frame.dw_max_video_frame_buffer_size = 460800; 2147 h->frame.dw_default_frame_interval = 666666; 2148 2149 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; 2150 opts = to_f_uvc_opts(opts_item); 2151 2152 mutex_lock(&opts->lock); 2153 fmt = to_uvcg_format(&group->cg_item); 2154 if (fmt->type == UVCG_UNCOMPRESSED) { 2155 h->frame.b_descriptor_subtype = UVC_VS_FRAME_UNCOMPRESSED; 2156 h->fmt_type = UVCG_UNCOMPRESSED; 2157 } else if (fmt->type == UVCG_MJPEG) { 2158 h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG; 2159 h->fmt_type = UVCG_MJPEG; 2160 } else { 2161 mutex_unlock(&opts->lock); 2162 kfree(h); 2163 return ERR_PTR(-EINVAL); 2164 } 2165 2166 frame_ptr = kzalloc(sizeof(*frame_ptr), GFP_KERNEL); 2167 if (!frame_ptr) { 2168 mutex_unlock(&opts->lock); 2169 kfree(h); 2170 return ERR_PTR(-ENOMEM); 2171 } 2172 2173 frame_ptr->frm = h; 2174 list_add_tail(&frame_ptr->entry, &fmt->frames); 2175 ++fmt->num_frames; 2176 mutex_unlock(&opts->lock); 2177 2178 config_item_init_type_name(&h->item, name, &uvcg_frame_type); 2179 2180 return &h->item; 2181} 2182 2183static void uvcg_frame_drop(struct config_group *group, struct config_item *item) 2184{ 2185 struct uvcg_format *fmt; 2186 struct f_uvc_opts *opts; 2187 struct config_item *opts_item; 2188 struct uvcg_frame *target_frm = NULL; 2189 struct uvcg_frame_ptr *frame_ptr, *tmp; 2190 2191 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; 2192 opts = to_f_uvc_opts(opts_item); 2193 2194 mutex_lock(&opts->lock); 2195 target_frm = container_of(item, struct uvcg_frame, item); 2196 fmt = to_uvcg_format(&group->cg_item); 2197 2198 list_for_each_entry_safe(frame_ptr, tmp, &fmt->frames, entry) 2199 if (frame_ptr->frm == target_frm) { 2200 list_del(&frame_ptr->entry); 2201 kfree(frame_ptr); 2202 --fmt->num_frames; 2203 break; 2204 } 2205 mutex_unlock(&opts->lock); 2206 2207 config_item_put(item); 2208} 2209 2210static void uvcg_format_set_indices(struct config_group *fmt) 2211{ 2212 struct config_item *ci; 2213 unsigned int i = 1; 2214 2215 list_for_each_entry(ci, &fmt->cg_children, ci_entry) { 2216 struct uvcg_frame *frm; 2217 2218 if (ci->ci_type != &uvcg_frame_type) 2219 continue; 2220 2221 frm = to_uvcg_frame(ci); 2222 frm->frame.b_frame_index = i++; 2223 } 2224} 2225 2226/* ----------------------------------------------------------------------------- 2227 * streaming/uncompressed/<NAME> 2228 */ 2229 2230static struct configfs_group_operations uvcg_uncompressed_group_ops = { 2231 .make_item = uvcg_frame_make, 2232 .drop_item = uvcg_frame_drop, 2233}; 2234 2235static ssize_t uvcg_uncompressed_guid_format_show(struct config_item *item, 2236 char *page) 2237{ 2238 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item); 2239 struct f_uvc_opts *opts; 2240 struct config_item *opts_item; 2241 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex; 2242 2243 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 2244 2245 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; 2246 opts = to_f_uvc_opts(opts_item); 2247 2248 mutex_lock(&opts->lock); 2249 memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat)); 2250 mutex_unlock(&opts->lock); 2251 2252 mutex_unlock(su_mutex); 2253 2254 return sizeof(ch->desc.guidFormat); 2255} 2256 2257static ssize_t uvcg_uncompressed_guid_format_store(struct config_item *item, 2258 const char *page, size_t len) 2259{ 2260 struct uvcg_uncompressed *ch = to_uvcg_uncompressed(item); 2261 struct f_uvc_opts *opts; 2262 struct config_item *opts_item; 2263 struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex; 2264 const struct uvc_format_desc *format; 2265 u8 tmpguidFormat[sizeof(ch->desc.guidFormat)]; 2266 int ret; 2267 2268 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 2269 2270 opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent; 2271 opts = to_f_uvc_opts(opts_item); 2272 2273 mutex_lock(&opts->lock); 2274 if (ch->fmt.linked || opts->refcnt) { 2275 ret = -EBUSY; 2276 goto end; 2277 } 2278 2279 memcpy(tmpguidFormat, page, 2280 min(sizeof(tmpguidFormat), len)); 2281 2282 format = uvc_format_by_guid(tmpguidFormat); 2283 if (!format) { 2284 ret = -EINVAL; 2285 goto end; 2286 } 2287 2288 memcpy(ch->desc.guidFormat, tmpguidFormat, 2289 min(sizeof(ch->desc.guidFormat), len)); 2290 ret = sizeof(ch->desc.guidFormat); 2291 2292end: 2293 mutex_unlock(&opts->lock); 2294 mutex_unlock(su_mutex); 2295 return ret; 2296} 2297 2298UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat); 2299 2300#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, bits) \ 2301static ssize_t uvcg_uncompressed_##cname##_show( \ 2302 struct config_item *item, char *page) \ 2303{ \ 2304 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \ 2305 struct f_uvc_opts *opts; \ 2306 struct config_item *opts_item; \ 2307 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 2308 int result; \ 2309 \ 2310 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2311 \ 2312 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 2313 opts = to_f_uvc_opts(opts_item); \ 2314 \ 2315 mutex_lock(&opts->lock); \ 2316 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ 2317 mutex_unlock(&opts->lock); \ 2318 \ 2319 mutex_unlock(su_mutex); \ 2320 return result; \ 2321} \ 2322 \ 2323UVC_ATTR_RO(uvcg_uncompressed_, cname, aname); 2324 2325#define UVCG_UNCOMPRESSED_ATTR(cname, aname, bits) \ 2326static ssize_t uvcg_uncompressed_##cname##_show( \ 2327 struct config_item *item, char *page) \ 2328{ \ 2329 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \ 2330 struct f_uvc_opts *opts; \ 2331 struct config_item *opts_item; \ 2332 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 2333 int result; \ 2334 \ 2335 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2336 \ 2337 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 2338 opts = to_f_uvc_opts(opts_item); \ 2339 \ 2340 mutex_lock(&opts->lock); \ 2341 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ 2342 mutex_unlock(&opts->lock); \ 2343 \ 2344 mutex_unlock(su_mutex); \ 2345 return result; \ 2346} \ 2347 \ 2348static ssize_t \ 2349uvcg_uncompressed_##cname##_store(struct config_item *item, \ 2350 const char *page, size_t len) \ 2351{ \ 2352 struct uvcg_uncompressed *u = to_uvcg_uncompressed(item); \ 2353 struct f_uvc_opts *opts; \ 2354 struct config_item *opts_item; \ 2355 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 2356 int ret; \ 2357 u8 num; \ 2358 \ 2359 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2360 \ 2361 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 2362 opts = to_f_uvc_opts(opts_item); \ 2363 \ 2364 mutex_lock(&opts->lock); \ 2365 if (u->fmt.linked || opts->refcnt) { \ 2366 ret = -EBUSY; \ 2367 goto end; \ 2368 } \ 2369 \ 2370 ret = kstrtou8(page, 0, &num); \ 2371 if (ret) \ 2372 goto end; \ 2373 \ 2374 /* index values in uvc are never 0 */ \ 2375 if (!num) { \ 2376 ret = -EINVAL; \ 2377 goto end; \ 2378 } \ 2379 \ 2380 u->desc.aname = num; \ 2381 ret = len; \ 2382end: \ 2383 mutex_unlock(&opts->lock); \ 2384 mutex_unlock(su_mutex); \ 2385 return ret; \ 2386} \ 2387 \ 2388UVC_ATTR(uvcg_uncompressed_, cname, aname); 2389 2390UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, 8); 2391UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8); 2392UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8); 2393UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8); 2394UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8); 2395UVCG_UNCOMPRESSED_ATTR_RO(bm_interlace_flags, bmInterlaceFlags, 8); 2396 2397#undef UVCG_UNCOMPRESSED_ATTR 2398#undef UVCG_UNCOMPRESSED_ATTR_RO 2399 2400static inline ssize_t 2401uvcg_uncompressed_bma_controls_show(struct config_item *item, char *page) 2402{ 2403 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item); 2404 return uvcg_format_bma_controls_show(&unc->fmt, page); 2405} 2406 2407static inline ssize_t 2408uvcg_uncompressed_bma_controls_store(struct config_item *item, 2409 const char *page, size_t len) 2410{ 2411 struct uvcg_uncompressed *unc = to_uvcg_uncompressed(item); 2412 return uvcg_format_bma_controls_store(&unc->fmt, page, len); 2413} 2414 2415UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls); 2416 2417static struct configfs_attribute *uvcg_uncompressed_attrs[] = { 2418 &uvcg_uncompressed_attr_b_format_index, 2419 &uvcg_uncompressed_attr_guid_format, 2420 &uvcg_uncompressed_attr_b_bits_per_pixel, 2421 &uvcg_uncompressed_attr_b_default_frame_index, 2422 &uvcg_uncompressed_attr_b_aspect_ratio_x, 2423 &uvcg_uncompressed_attr_b_aspect_ratio_y, 2424 &uvcg_uncompressed_attr_bm_interlace_flags, 2425 &uvcg_uncompressed_attr_bma_controls, 2426 NULL, 2427}; 2428 2429static const struct config_item_type uvcg_uncompressed_type = { 2430 .ct_item_ops = &uvcg_format_item_operations, 2431 .ct_group_ops = &uvcg_uncompressed_group_ops, 2432 .ct_attrs = uvcg_uncompressed_attrs, 2433 .ct_owner = THIS_MODULE, 2434}; 2435 2436static struct config_group *uvcg_uncompressed_make(struct config_group *group, 2437 const char *name) 2438{ 2439 static char guid[] = { 2440 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 2441 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 2442 }; 2443 struct uvcg_color_matching *color_match; 2444 struct config_item *streaming; 2445 struct uvcg_uncompressed *h; 2446 2447 streaming = group->cg_item.ci_parent; 2448 color_match = uvcg_format_get_default_color_match(streaming); 2449 if (!color_match) 2450 return ERR_PTR(-EINVAL); 2451 2452 h = kzalloc(sizeof(*h), GFP_KERNEL); 2453 if (!h) 2454 return ERR_PTR(-ENOMEM); 2455 2456 h->desc.bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE; 2457 h->desc.bDescriptorType = USB_DT_CS_INTERFACE; 2458 h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED; 2459 memcpy(h->desc.guidFormat, guid, sizeof(guid)); 2460 h->desc.bBitsPerPixel = 16; 2461 h->desc.bDefaultFrameIndex = 1; 2462 h->desc.bAspectRatioX = 0; 2463 h->desc.bAspectRatioY = 0; 2464 h->desc.bmInterlaceFlags = 0; 2465 h->desc.bCopyProtect = 0; 2466 2467 INIT_LIST_HEAD(&h->fmt.frames); 2468 h->fmt.type = UVCG_UNCOMPRESSED; 2469 h->fmt.color_matching = color_match; 2470 color_match->refcnt++; 2471 config_group_init_type_name(&h->fmt.group, name, 2472 &uvcg_uncompressed_type); 2473 2474 return &h->fmt.group; 2475} 2476 2477static struct configfs_group_operations uvcg_uncompressed_grp_ops = { 2478 .make_group = uvcg_uncompressed_make, 2479}; 2480 2481static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = { 2482 .type = { 2483 .ct_item_ops = &uvcg_config_item_ops, 2484 .ct_group_ops = &uvcg_uncompressed_grp_ops, 2485 .ct_owner = THIS_MODULE, 2486 }, 2487 .name = "uncompressed", 2488}; 2489 2490/* ----------------------------------------------------------------------------- 2491 * streaming/mjpeg/<NAME> 2492 */ 2493 2494static struct configfs_group_operations uvcg_mjpeg_group_ops = { 2495 .make_item = uvcg_frame_make, 2496 .drop_item = uvcg_frame_drop, 2497}; 2498 2499#define UVCG_MJPEG_ATTR_RO(cname, aname, bits) \ 2500static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ 2501{ \ 2502 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ 2503 struct f_uvc_opts *opts; \ 2504 struct config_item *opts_item; \ 2505 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 2506 int result; \ 2507 \ 2508 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2509 \ 2510 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 2511 opts = to_f_uvc_opts(opts_item); \ 2512 \ 2513 mutex_lock(&opts->lock); \ 2514 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ 2515 mutex_unlock(&opts->lock); \ 2516 \ 2517 mutex_unlock(su_mutex); \ 2518 return result; \ 2519} \ 2520 \ 2521UVC_ATTR_RO(uvcg_mjpeg_, cname, aname) 2522 2523#define UVCG_MJPEG_ATTR(cname, aname, bits) \ 2524static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\ 2525{ \ 2526 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ 2527 struct f_uvc_opts *opts; \ 2528 struct config_item *opts_item; \ 2529 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 2530 int result; \ 2531 \ 2532 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2533 \ 2534 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 2535 opts = to_f_uvc_opts(opts_item); \ 2536 \ 2537 mutex_lock(&opts->lock); \ 2538 result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\ 2539 mutex_unlock(&opts->lock); \ 2540 \ 2541 mutex_unlock(su_mutex); \ 2542 return result; \ 2543} \ 2544 \ 2545static ssize_t \ 2546uvcg_mjpeg_##cname##_store(struct config_item *item, \ 2547 const char *page, size_t len) \ 2548{ \ 2549 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \ 2550 struct f_uvc_opts *opts; \ 2551 struct config_item *opts_item; \ 2552 struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \ 2553 int ret; \ 2554 u8 num; \ 2555 \ 2556 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2557 \ 2558 opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\ 2559 opts = to_f_uvc_opts(opts_item); \ 2560 \ 2561 mutex_lock(&opts->lock); \ 2562 if (u->fmt.linked || opts->refcnt) { \ 2563 ret = -EBUSY; \ 2564 goto end; \ 2565 } \ 2566 \ 2567 ret = kstrtou8(page, 0, &num); \ 2568 if (ret) \ 2569 goto end; \ 2570 \ 2571 /* index values in uvc are never 0 */ \ 2572 if (!num) { \ 2573 ret = -EINVAL; \ 2574 goto end; \ 2575 } \ 2576 \ 2577 u->desc.aname = num; \ 2578 ret = len; \ 2579end: \ 2580 mutex_unlock(&opts->lock); \ 2581 mutex_unlock(su_mutex); \ 2582 return ret; \ 2583} \ 2584 \ 2585UVC_ATTR(uvcg_mjpeg_, cname, aname) 2586 2587UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, 8); 2588UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8); 2589UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8); 2590UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8); 2591UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8); 2592UVCG_MJPEG_ATTR_RO(bm_interlace_flags, bmInterlaceFlags, 8); 2593 2594#undef UVCG_MJPEG_ATTR 2595#undef UVCG_MJPEG_ATTR_RO 2596 2597static inline ssize_t 2598uvcg_mjpeg_bma_controls_show(struct config_item *item, char *page) 2599{ 2600 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); 2601 return uvcg_format_bma_controls_show(&u->fmt, page); 2602} 2603 2604static inline ssize_t 2605uvcg_mjpeg_bma_controls_store(struct config_item *item, 2606 const char *page, size_t len) 2607{ 2608 struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); 2609 return uvcg_format_bma_controls_store(&u->fmt, page, len); 2610} 2611 2612UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls); 2613 2614static struct configfs_attribute *uvcg_mjpeg_attrs[] = { 2615 &uvcg_mjpeg_attr_b_format_index, 2616 &uvcg_mjpeg_attr_b_default_frame_index, 2617 &uvcg_mjpeg_attr_bm_flags, 2618 &uvcg_mjpeg_attr_b_aspect_ratio_x, 2619 &uvcg_mjpeg_attr_b_aspect_ratio_y, 2620 &uvcg_mjpeg_attr_bm_interlace_flags, 2621 &uvcg_mjpeg_attr_bma_controls, 2622 NULL, 2623}; 2624 2625static const struct config_item_type uvcg_mjpeg_type = { 2626 .ct_item_ops = &uvcg_format_item_operations, 2627 .ct_group_ops = &uvcg_mjpeg_group_ops, 2628 .ct_attrs = uvcg_mjpeg_attrs, 2629 .ct_owner = THIS_MODULE, 2630}; 2631 2632static struct config_group *uvcg_mjpeg_make(struct config_group *group, 2633 const char *name) 2634{ 2635 struct uvcg_color_matching *color_match; 2636 struct config_item *streaming; 2637 struct uvcg_mjpeg *h; 2638 2639 streaming = group->cg_item.ci_parent; 2640 color_match = uvcg_format_get_default_color_match(streaming); 2641 if (!color_match) 2642 return ERR_PTR(-EINVAL); 2643 2644 h = kzalloc(sizeof(*h), GFP_KERNEL); 2645 if (!h) 2646 return ERR_PTR(-ENOMEM); 2647 2648 h->desc.bLength = UVC_DT_FORMAT_MJPEG_SIZE; 2649 h->desc.bDescriptorType = USB_DT_CS_INTERFACE; 2650 h->desc.bDescriptorSubType = UVC_VS_FORMAT_MJPEG; 2651 h->desc.bDefaultFrameIndex = 1; 2652 h->desc.bAspectRatioX = 0; 2653 h->desc.bAspectRatioY = 0; 2654 h->desc.bmInterlaceFlags = 0; 2655 h->desc.bCopyProtect = 0; 2656 2657 INIT_LIST_HEAD(&h->fmt.frames); 2658 h->fmt.type = UVCG_MJPEG; 2659 h->fmt.color_matching = color_match; 2660 color_match->refcnt++; 2661 config_group_init_type_name(&h->fmt.group, name, 2662 &uvcg_mjpeg_type); 2663 2664 return &h->fmt.group; 2665} 2666 2667static struct configfs_group_operations uvcg_mjpeg_grp_ops = { 2668 .make_group = uvcg_mjpeg_make, 2669}; 2670 2671static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = { 2672 .type = { 2673 .ct_item_ops = &uvcg_config_item_ops, 2674 .ct_group_ops = &uvcg_mjpeg_grp_ops, 2675 .ct_owner = THIS_MODULE, 2676 }, 2677 .name = "mjpeg", 2678}; 2679 2680/* ----------------------------------------------------------------------------- 2681 * streaming/color_matching/default 2682 */ 2683 2684#define UVCG_COLOR_MATCHING_ATTR(cname, aname, bits) \ 2685static ssize_t uvcg_color_matching_##cname##_show( \ 2686 struct config_item *item, char *page) \ 2687{ \ 2688 struct config_group *group = to_config_group(item); \ 2689 struct uvcg_color_matching *color_match = \ 2690 to_uvcg_color_matching(group); \ 2691 struct f_uvc_opts *opts; \ 2692 struct config_item *opts_item; \ 2693 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ 2694 int result; \ 2695 \ 2696 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2697 \ 2698 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \ 2699 opts = to_f_uvc_opts(opts_item); \ 2700 \ 2701 mutex_lock(&opts->lock); \ 2702 result = sprintf(page, "%u\n", \ 2703 le##bits##_to_cpu(color_match->desc.aname)); \ 2704 mutex_unlock(&opts->lock); \ 2705 \ 2706 mutex_unlock(su_mutex); \ 2707 return result; \ 2708} \ 2709 \ 2710static ssize_t uvcg_color_matching_##cname##_store( \ 2711 struct config_item *item, const char *page, size_t len) \ 2712{ \ 2713 struct config_group *group = to_config_group(item); \ 2714 struct mutex *su_mutex = &group->cg_subsys->su_mutex; \ 2715 struct uvcg_color_matching *color_match = \ 2716 to_uvcg_color_matching(group); \ 2717 struct f_uvc_opts *opts; \ 2718 struct config_item *opts_item; \ 2719 int ret; \ 2720 u##bits num; \ 2721 \ 2722 ret = kstrtou##bits(page, 0, &num); \ 2723 if (ret) \ 2724 return ret; \ 2725 \ 2726 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \ 2727 \ 2728 if (color_match->refcnt) { \ 2729 ret = -EBUSY; \ 2730 goto unlock_su; \ 2731 } \ 2732 \ 2733 opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \ 2734 opts = to_f_uvc_opts(opts_item); \ 2735 \ 2736 mutex_lock(&opts->lock); \ 2737 \ 2738 color_match->desc.aname = num; \ 2739 ret = len; \ 2740 \ 2741 mutex_unlock(&opts->lock); \ 2742unlock_su: \ 2743 mutex_unlock(su_mutex); \ 2744 \ 2745 return ret; \ 2746} \ 2747UVC_ATTR(uvcg_color_matching_, cname, aname) 2748 2749UVCG_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 8); 2750UVCG_COLOR_MATCHING_ATTR(b_transfer_characteristics, bTransferCharacteristics, 8); 2751UVCG_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 8); 2752 2753#undef UVCG_COLOR_MATCHING_ATTR 2754 2755static struct configfs_attribute *uvcg_color_matching_attrs[] = { 2756 &uvcg_color_matching_attr_b_color_primaries, 2757 &uvcg_color_matching_attr_b_transfer_characteristics, 2758 &uvcg_color_matching_attr_b_matrix_coefficients, 2759 NULL, 2760}; 2761 2762static void uvcg_color_matching_release(struct config_item *item) 2763{ 2764 struct uvcg_color_matching *color_match = 2765 to_uvcg_color_matching(to_config_group(item)); 2766 2767 kfree(color_match); 2768} 2769 2770static struct configfs_item_operations uvcg_color_matching_item_ops = { 2771 .release = uvcg_color_matching_release, 2772}; 2773 2774static const struct config_item_type uvcg_color_matching_type = { 2775 .ct_item_ops = &uvcg_color_matching_item_ops, 2776 .ct_attrs = uvcg_color_matching_attrs, 2777 .ct_owner = THIS_MODULE, 2778}; 2779 2780/* ----------------------------------------------------------------------------- 2781 * streaming/color_matching 2782 */ 2783 2784static struct config_group *uvcg_color_matching_make(struct config_group *group, 2785 const char *name) 2786{ 2787 struct uvcg_color_matching *color_match; 2788 2789 color_match = kzalloc(sizeof(*color_match), GFP_KERNEL); 2790 if (!color_match) 2791 return ERR_PTR(-ENOMEM); 2792 2793 color_match->desc.bLength = UVC_DT_COLOR_MATCHING_SIZE; 2794 color_match->desc.bDescriptorType = USB_DT_CS_INTERFACE; 2795 color_match->desc.bDescriptorSubType = UVC_VS_COLORFORMAT; 2796 2797 config_group_init_type_name(&color_match->group, name, 2798 &uvcg_color_matching_type); 2799 2800 return &color_match->group; 2801} 2802 2803static struct configfs_group_operations uvcg_color_matching_grp_group_ops = { 2804 .make_group = uvcg_color_matching_make, 2805}; 2806 2807static int uvcg_color_matching_create_children(struct config_group *parent) 2808{ 2809 struct uvcg_color_matching *color_match; 2810 2811 color_match = kzalloc(sizeof(*color_match), GFP_KERNEL); 2812 if (!color_match) 2813 return -ENOMEM; 2814 2815 color_match->desc.bLength = UVC_DT_COLOR_MATCHING_SIZE; 2816 color_match->desc.bDescriptorType = USB_DT_CS_INTERFACE; 2817 color_match->desc.bDescriptorSubType = UVC_VS_COLORFORMAT; 2818 color_match->desc.bColorPrimaries = UVC_COLOR_PRIMARIES_BT_709_SRGB; 2819 color_match->desc.bTransferCharacteristics = UVC_TRANSFER_CHARACTERISTICS_BT_709; 2820 color_match->desc.bMatrixCoefficients = UVC_MATRIX_COEFFICIENTS_SMPTE_170M; 2821 2822 config_group_init_type_name(&color_match->group, "default", 2823 &uvcg_color_matching_type); 2824 configfs_add_default_group(&color_match->group, parent); 2825 2826 return 0; 2827} 2828 2829static const struct uvcg_config_group_type uvcg_color_matching_grp_type = { 2830 .type = { 2831 .ct_item_ops = &uvcg_config_item_ops, 2832 .ct_group_ops = &uvcg_color_matching_grp_group_ops, 2833 .ct_owner = THIS_MODULE, 2834 }, 2835 .name = "color_matching", 2836 .create_children = uvcg_color_matching_create_children, 2837}; 2838 2839/* ----------------------------------------------------------------------------- 2840 * streaming/class/{fs|hs|ss} 2841 */ 2842 2843struct uvcg_streaming_class_group { 2844 struct config_group group; 2845 const char *name; 2846}; 2847 2848static inline struct uvc_descriptor_header 2849***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o) 2850{ 2851 struct uvcg_streaming_class_group *group = 2852 container_of(i, struct uvcg_streaming_class_group, 2853 group.cg_item); 2854 2855 if (!strcmp(group->name, "fs")) 2856 return &o->uvc_fs_streaming_cls; 2857 2858 if (!strcmp(group->name, "hs")) 2859 return &o->uvc_hs_streaming_cls; 2860 2861 if (!strcmp(group->name, "ss")) 2862 return &o->uvc_ss_streaming_cls; 2863 2864 return NULL; 2865} 2866 2867enum uvcg_strm_type { 2868 UVCG_HEADER = 0, 2869 UVCG_FORMAT, 2870 UVCG_FRAME, 2871 UVCG_COLOR_MATCHING, 2872}; 2873 2874/* 2875 * Iterate over a hierarchy of streaming descriptors' config items. 2876 * The items are created by the user with configfs. 2877 * 2878 * It "processes" the header pointed to by @priv1, then for each format 2879 * that follows the header "processes" the format itself and then for 2880 * each frame inside a format "processes" the frame. 2881 * 2882 * As a "processing" function the @fun is used. 2883 * 2884 * __uvcg_iter_strm_cls() is used in two context: first, to calculate 2885 * the amount of memory needed for an array of streaming descriptors 2886 * and second, to actually fill the array. 2887 * 2888 * @h: streaming header pointer 2889 * @priv2: an "inout" parameter (the caller might want to see the changes to it) 2890 * @priv3: an "inout" parameter (the caller might want to see the changes to it) 2891 * @fun: callback function for processing each level of the hierarchy 2892 */ 2893static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h, 2894 void *priv2, void *priv3, 2895 int (*fun)(void *, void *, void *, int, enum uvcg_strm_type type)) 2896{ 2897 struct uvcg_format_ptr *f; 2898 struct config_group *grp; 2899 struct config_item *item; 2900 struct uvcg_frame *frm; 2901 int ret, i, j; 2902 2903 if (!fun) 2904 return -EINVAL; 2905 2906 i = j = 0; 2907 ret = fun(h, priv2, priv3, 0, UVCG_HEADER); 2908 if (ret) 2909 return ret; 2910 list_for_each_entry(f, &h->formats, entry) { 2911 ret = fun(f->fmt, priv2, priv3, i++, UVCG_FORMAT); 2912 if (ret) 2913 return ret; 2914 grp = &f->fmt->group; 2915 list_for_each_entry(item, &grp->cg_children, ci_entry) { 2916 frm = to_uvcg_frame(item); 2917 ret = fun(frm, priv2, priv3, j++, UVCG_FRAME); 2918 if (ret) 2919 return ret; 2920 } 2921 2922 ret = fun(f->fmt->color_matching, priv2, priv3, 0, 2923 UVCG_COLOR_MATCHING); 2924 if (ret) 2925 return ret; 2926 } 2927 2928 return ret; 2929} 2930 2931/* 2932 * Count how many bytes are needed for an array of streaming descriptors. 2933 * 2934 * @priv1: pointer to a header, format or frame 2935 * @priv2: inout parameter, accumulated size of the array 2936 * @priv3: inout parameter, accumulated number of the array elements 2937 * @n: unused, this function's prototype must match @fun in __uvcg_iter_strm_cls 2938 */ 2939static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n, 2940 enum uvcg_strm_type type) 2941{ 2942 size_t *size = priv2; 2943 size_t *count = priv3; 2944 2945 switch (type) { 2946 case UVCG_HEADER: { 2947 struct uvcg_streaming_header *h = priv1; 2948 2949 *size += sizeof(h->desc); 2950 /* bmaControls */ 2951 *size += h->num_fmt * UVCG_STREAMING_CONTROL_SIZE; 2952 } 2953 break; 2954 case UVCG_FORMAT: { 2955 struct uvcg_format *fmt = priv1; 2956 2957 if (fmt->type == UVCG_UNCOMPRESSED) { 2958 struct uvcg_uncompressed *u = 2959 container_of(fmt, struct uvcg_uncompressed, 2960 fmt); 2961 2962 *size += sizeof(u->desc); 2963 } else if (fmt->type == UVCG_MJPEG) { 2964 struct uvcg_mjpeg *m = 2965 container_of(fmt, struct uvcg_mjpeg, fmt); 2966 2967 *size += sizeof(m->desc); 2968 } else { 2969 return -EINVAL; 2970 } 2971 } 2972 break; 2973 case UVCG_FRAME: { 2974 struct uvcg_frame *frm = priv1; 2975 int sz = sizeof(frm->dw_frame_interval); 2976 2977 *size += sizeof(frm->frame); 2978 *size += frm->frame.b_frame_interval_type * sz; 2979 } 2980 break; 2981 case UVCG_COLOR_MATCHING: { 2982 struct uvcg_color_matching *color_match = priv1; 2983 2984 *size += sizeof(color_match->desc); 2985 } 2986 break; 2987 } 2988 2989 ++*count; 2990 2991 return 0; 2992} 2993 2994/* 2995 * Fill an array of streaming descriptors. 2996 * 2997 * @priv1: pointer to a header, format or frame 2998 * @priv2: inout parameter, pointer into a block of memory 2999 * @priv3: inout parameter, pointer to a 2-dimensional array 3000 */ 3001static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n, 3002 enum uvcg_strm_type type) 3003{ 3004 void **dest = priv2; 3005 struct uvc_descriptor_header ***array = priv3; 3006 size_t sz; 3007 3008 **array = *dest; 3009 ++*array; 3010 3011 switch (type) { 3012 case UVCG_HEADER: { 3013 struct uvc_input_header_descriptor *ihdr = *dest; 3014 struct uvcg_streaming_header *h = priv1; 3015 struct uvcg_format_ptr *f; 3016 3017 memcpy(*dest, &h->desc, sizeof(h->desc)); 3018 *dest += sizeof(h->desc); 3019 sz = UVCG_STREAMING_CONTROL_SIZE; 3020 list_for_each_entry(f, &h->formats, entry) { 3021 memcpy(*dest, f->fmt->bmaControls, sz); 3022 *dest += sz; 3023 } 3024 ihdr->bLength = sizeof(h->desc) + h->num_fmt * sz; 3025 ihdr->bNumFormats = h->num_fmt; 3026 } 3027 break; 3028 case UVCG_FORMAT: { 3029 struct uvcg_format *fmt = priv1; 3030 3031 if (fmt->type == UVCG_UNCOMPRESSED) { 3032 struct uvcg_uncompressed *u = 3033 container_of(fmt, struct uvcg_uncompressed, 3034 fmt); 3035 3036 u->desc.bFormatIndex = n + 1; 3037 u->desc.bNumFrameDescriptors = fmt->num_frames; 3038 memcpy(*dest, &u->desc, sizeof(u->desc)); 3039 *dest += sizeof(u->desc); 3040 } else if (fmt->type == UVCG_MJPEG) { 3041 struct uvcg_mjpeg *m = 3042 container_of(fmt, struct uvcg_mjpeg, fmt); 3043 3044 m->desc.bFormatIndex = n + 1; 3045 m->desc.bNumFrameDescriptors = fmt->num_frames; 3046 memcpy(*dest, &m->desc, sizeof(m->desc)); 3047 *dest += sizeof(m->desc); 3048 } else { 3049 return -EINVAL; 3050 } 3051 } 3052 break; 3053 case UVCG_FRAME: { 3054 struct uvcg_frame *frm = priv1; 3055 struct uvc_descriptor_header *h = *dest; 3056 3057 sz = sizeof(frm->frame); 3058 memcpy(*dest, &frm->frame, sz); 3059 *dest += sz; 3060 sz = frm->frame.b_frame_interval_type * 3061 sizeof(*frm->dw_frame_interval); 3062 memcpy(*dest, frm->dw_frame_interval, sz); 3063 *dest += sz; 3064 if (frm->fmt_type == UVCG_UNCOMPRESSED) 3065 h->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE( 3066 frm->frame.b_frame_interval_type); 3067 else if (frm->fmt_type == UVCG_MJPEG) 3068 h->bLength = UVC_DT_FRAME_MJPEG_SIZE( 3069 frm->frame.b_frame_interval_type); 3070 } 3071 break; 3072 case UVCG_COLOR_MATCHING: { 3073 struct uvcg_color_matching *color_match = priv1; 3074 3075 memcpy(*dest, &color_match->desc, sizeof(color_match->desc)); 3076 *dest += sizeof(color_match->desc); 3077 } 3078 break; 3079 } 3080 3081 return 0; 3082} 3083 3084static int uvcg_streaming_class_allow_link(struct config_item *src, 3085 struct config_item *target) 3086{ 3087 struct config_item *streaming, *header; 3088 struct f_uvc_opts *opts; 3089 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 3090 struct uvc_descriptor_header ***class_array, **cl_arr; 3091 struct uvcg_streaming_header *target_hdr; 3092 void *data, *data_save; 3093 size_t size = 0, count = 0; 3094 int ret = -EINVAL; 3095 3096 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 3097 3098 streaming = src->ci_parent->ci_parent; 3099 header = config_group_find_item(to_config_group(streaming), "header"); 3100 if (!header || target->ci_parent != header) 3101 goto out; 3102 3103 opts = to_f_uvc_opts(streaming->ci_parent); 3104 3105 mutex_lock(&opts->lock); 3106 3107 class_array = __uvcg_get_stream_class_arr(src, opts); 3108 if (!class_array || *class_array || opts->refcnt) { 3109 ret = -EBUSY; 3110 goto unlock; 3111 } 3112 3113 target_hdr = to_uvcg_streaming_header(target); 3114 ret = __uvcg_iter_strm_cls(target_hdr, &size, &count, __uvcg_cnt_strm); 3115 if (ret) 3116 goto unlock; 3117 3118 count += 1; /* NULL */ 3119 *class_array = kcalloc(count, sizeof(void *), GFP_KERNEL); 3120 if (!*class_array) { 3121 ret = -ENOMEM; 3122 goto unlock; 3123 } 3124 3125 data = data_save = kzalloc(size, GFP_KERNEL); 3126 if (!data) { 3127 kfree(*class_array); 3128 *class_array = NULL; 3129 ret = -ENOMEM; 3130 goto unlock; 3131 } 3132 cl_arr = *class_array; 3133 ret = __uvcg_iter_strm_cls(target_hdr, &data, &cl_arr, 3134 __uvcg_fill_strm); 3135 if (ret) { 3136 kfree(*class_array); 3137 *class_array = NULL; 3138 /* 3139 * __uvcg_fill_strm() called from __uvcg_iter_stream_cls() 3140 * might have advanced the "data", so use a backup copy 3141 */ 3142 kfree(data_save); 3143 goto unlock; 3144 } 3145 3146 ++target_hdr->linked; 3147 ret = 0; 3148 3149unlock: 3150 mutex_unlock(&opts->lock); 3151out: 3152 config_item_put(header); 3153 mutex_unlock(su_mutex); 3154 return ret; 3155} 3156 3157static void uvcg_streaming_class_drop_link(struct config_item *src, 3158 struct config_item *target) 3159{ 3160 struct config_item *streaming, *header; 3161 struct f_uvc_opts *opts; 3162 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 3163 struct uvc_descriptor_header ***class_array; 3164 struct uvcg_streaming_header *target_hdr; 3165 3166 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 3167 3168 streaming = src->ci_parent->ci_parent; 3169 header = config_group_find_item(to_config_group(streaming), "header"); 3170 if (!header || target->ci_parent != header) 3171 goto out; 3172 3173 opts = to_f_uvc_opts(streaming->ci_parent); 3174 3175 mutex_lock(&opts->lock); 3176 3177 class_array = __uvcg_get_stream_class_arr(src, opts); 3178 if (!class_array || !*class_array) 3179 goto unlock; 3180 3181 if (opts->refcnt) 3182 goto unlock; 3183 3184 target_hdr = to_uvcg_streaming_header(target); 3185 --target_hdr->linked; 3186 kfree(**class_array); 3187 kfree(*class_array); 3188 *class_array = NULL; 3189 3190unlock: 3191 mutex_unlock(&opts->lock); 3192out: 3193 config_item_put(header); 3194 mutex_unlock(su_mutex); 3195} 3196 3197static struct configfs_item_operations uvcg_streaming_class_item_ops = { 3198 .release = uvcg_config_item_release, 3199 .allow_link = uvcg_streaming_class_allow_link, 3200 .drop_link = uvcg_streaming_class_drop_link, 3201}; 3202 3203static const struct config_item_type uvcg_streaming_class_type = { 3204 .ct_item_ops = &uvcg_streaming_class_item_ops, 3205 .ct_owner = THIS_MODULE, 3206}; 3207 3208/* ----------------------------------------------------------------------------- 3209 * streaming/class 3210 */ 3211 3212static int uvcg_streaming_class_create_children(struct config_group *parent) 3213{ 3214 static const char * const names[] = { "fs", "hs", "ss" }; 3215 unsigned int i; 3216 3217 for (i = 0; i < ARRAY_SIZE(names); ++i) { 3218 struct uvcg_streaming_class_group *group; 3219 3220 group = kzalloc(sizeof(*group), GFP_KERNEL); 3221 if (!group) 3222 return -ENOMEM; 3223 3224 group->name = names[i]; 3225 3226 config_group_init_type_name(&group->group, group->name, 3227 &uvcg_streaming_class_type); 3228 configfs_add_default_group(&group->group, parent); 3229 } 3230 3231 return 0; 3232} 3233 3234static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = { 3235 .type = { 3236 .ct_item_ops = &uvcg_config_item_ops, 3237 .ct_owner = THIS_MODULE, 3238 }, 3239 .name = "class", 3240 .create_children = uvcg_streaming_class_create_children, 3241}; 3242 3243/* ----------------------------------------------------------------------------- 3244 * streaming 3245 */ 3246 3247static ssize_t uvcg_default_streaming_b_interface_number_show( 3248 struct config_item *item, char *page) 3249{ 3250 struct config_group *group = to_config_group(item); 3251 struct mutex *su_mutex = &group->cg_subsys->su_mutex; 3252 struct config_item *opts_item; 3253 struct f_uvc_opts *opts; 3254 int result = 0; 3255 3256 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 3257 3258 opts_item = item->ci_parent; 3259 opts = to_f_uvc_opts(opts_item); 3260 3261 mutex_lock(&opts->lock); 3262 result += sprintf(page, "%u\n", opts->streaming_interface); 3263 mutex_unlock(&opts->lock); 3264 3265 mutex_unlock(su_mutex); 3266 3267 return result; 3268} 3269 3270UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber); 3271 3272static struct configfs_attribute *uvcg_default_streaming_attrs[] = { 3273 &uvcg_default_streaming_attr_b_interface_number, 3274 NULL, 3275}; 3276 3277static const struct uvcg_config_group_type uvcg_streaming_grp_type = { 3278 .type = { 3279 .ct_item_ops = &uvcg_config_item_ops, 3280 .ct_attrs = uvcg_default_streaming_attrs, 3281 .ct_owner = THIS_MODULE, 3282 }, 3283 .name = "streaming", 3284 .children = (const struct uvcg_config_group_type*[]) { 3285 &uvcg_streaming_header_grp_type, 3286 &uvcg_uncompressed_grp_type, 3287 &uvcg_mjpeg_grp_type, 3288 &uvcg_color_matching_grp_type, 3289 &uvcg_streaming_class_grp_type, 3290 NULL, 3291 }, 3292}; 3293 3294/* ----------------------------------------------------------------------------- 3295 * UVC function 3296 */ 3297 3298static void uvc_func_item_release(struct config_item *item) 3299{ 3300 struct f_uvc_opts *opts = to_f_uvc_opts(item); 3301 3302 uvcg_config_remove_children(to_config_group(item)); 3303 usb_put_function_instance(&opts->func_inst); 3304} 3305 3306static int uvc_func_allow_link(struct config_item *src, struct config_item *tgt) 3307{ 3308 struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex; 3309 struct gadget_string *string; 3310 struct config_item *strings; 3311 struct f_uvc_opts *opts; 3312 int ret = 0; 3313 3314 mutex_lock(su_mutex); /* for navigating configfs hierarchy */ 3315 3316 /* Validate that the target is an entry in strings/<langid> */ 3317 strings = config_group_find_item(to_config_group(src->ci_parent->ci_parent), 3318 "strings"); 3319 if (!strings || tgt->ci_parent->ci_parent != strings) { 3320 ret = -EINVAL; 3321 goto put_strings; 3322 } 3323 3324 string = to_gadget_string(tgt); 3325 3326 opts = to_f_uvc_opts(src); 3327 mutex_lock(&opts->lock); 3328 3329 if (!strcmp(tgt->ci_name, "iad_desc")) 3330 opts->iad_index = string->usb_string.id; 3331 else if (!strcmp(tgt->ci_name, "vs0_desc")) 3332 opts->vs0_index = string->usb_string.id; 3333 else if (!strcmp(tgt->ci_name, "vs1_desc")) 3334 opts->vs1_index = string->usb_string.id; 3335 else 3336 ret = -EINVAL; 3337 3338 mutex_unlock(&opts->lock); 3339 3340put_strings: 3341 config_item_put(strings); 3342 mutex_unlock(su_mutex); 3343 3344 return ret; 3345} 3346 3347static void uvc_func_drop_link(struct config_item *src, struct config_item *tgt) 3348{ 3349 struct f_uvc_opts *opts; 3350 3351 opts = to_f_uvc_opts(src); 3352 mutex_lock(&opts->lock); 3353 3354 if (!strcmp(tgt->ci_name, "iad_desc")) 3355 opts->iad_index = 0; 3356 else if (!strcmp(tgt->ci_name, "vs0_desc")) 3357 opts->vs0_index = 0; 3358 else if (!strcmp(tgt->ci_name, "vs1_desc")) 3359 opts->vs1_index = 0; 3360 3361 mutex_unlock(&opts->lock); 3362} 3363 3364static struct configfs_item_operations uvc_func_item_ops = { 3365 .release = uvc_func_item_release, 3366 .allow_link = uvc_func_allow_link, 3367 .drop_link = uvc_func_drop_link, 3368}; 3369 3370#define UVCG_OPTS_ATTR(cname, aname, limit) \ 3371static ssize_t f_uvc_opts_##cname##_show( \ 3372 struct config_item *item, char *page) \ 3373{ \ 3374 struct f_uvc_opts *opts = to_f_uvc_opts(item); \ 3375 int result; \ 3376 \ 3377 mutex_lock(&opts->lock); \ 3378 result = sprintf(page, "%u\n", opts->cname); \ 3379 mutex_unlock(&opts->lock); \ 3380 \ 3381 return result; \ 3382} \ 3383 \ 3384static ssize_t \ 3385f_uvc_opts_##cname##_store(struct config_item *item, \ 3386 const char *page, size_t len) \ 3387{ \ 3388 struct f_uvc_opts *opts = to_f_uvc_opts(item); \ 3389 unsigned int num; \ 3390 int ret; \ 3391 \ 3392 mutex_lock(&opts->lock); \ 3393 if (opts->refcnt) { \ 3394 ret = -EBUSY; \ 3395 goto end; \ 3396 } \ 3397 \ 3398 ret = kstrtouint(page, 0, &num); \ 3399 if (ret) \ 3400 goto end; \ 3401 \ 3402 if (num > limit) { \ 3403 ret = -EINVAL; \ 3404 goto end; \ 3405 } \ 3406 opts->cname = num; \ 3407 ret = len; \ 3408end: \ 3409 mutex_unlock(&opts->lock); \ 3410 return ret; \ 3411} \ 3412 \ 3413UVC_ATTR(f_uvc_opts_, cname, cname) 3414 3415UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16); 3416UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072); 3417UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15); 3418 3419#undef UVCG_OPTS_ATTR 3420 3421#define UVCG_OPTS_STRING_ATTR(cname, aname) \ 3422static ssize_t f_uvc_opts_string_##cname##_show(struct config_item *item,\ 3423 char *page) \ 3424{ \ 3425 struct f_uvc_opts *opts = to_f_uvc_opts(item); \ 3426 int result; \ 3427 \ 3428 mutex_lock(&opts->lock); \ 3429 result = scnprintf(page, sizeof(opts->aname), "%s", opts->aname);\ 3430 mutex_unlock(&opts->lock); \ 3431 \ 3432 return result; \ 3433} \ 3434 \ 3435static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\ 3436 const char *page, size_t len) \ 3437{ \ 3438 struct f_uvc_opts *opts = to_f_uvc_opts(item); \ 3439 int size = min(sizeof(opts->aname), len + 1); \ 3440 int ret = 0; \ 3441 \ 3442 mutex_lock(&opts->lock); \ 3443 if (opts->refcnt) { \ 3444 ret = -EBUSY; \ 3445 goto end; \ 3446 } \ 3447 \ 3448 ret = strscpy(opts->aname, page, size); \ 3449 if (ret == -E2BIG) \ 3450 ret = size - 1; \ 3451 \ 3452end: \ 3453 mutex_unlock(&opts->lock); \ 3454 return ret; \ 3455} \ 3456 \ 3457UVC_ATTR(f_uvc_opts_string_, cname, aname) 3458 3459UVCG_OPTS_STRING_ATTR(function_name, function_name); 3460 3461#undef UVCG_OPTS_STRING_ATTR 3462 3463static struct configfs_attribute *uvc_attrs[] = { 3464 &f_uvc_opts_attr_streaming_interval, 3465 &f_uvc_opts_attr_streaming_maxpacket, 3466 &f_uvc_opts_attr_streaming_maxburst, 3467 &f_uvc_opts_string_attr_function_name, 3468 NULL, 3469}; 3470 3471static const struct uvcg_config_group_type uvc_func_type = { 3472 .type = { 3473 .ct_item_ops = &uvc_func_item_ops, 3474 .ct_attrs = uvc_attrs, 3475 .ct_owner = THIS_MODULE, 3476 }, 3477 .name = "", 3478 .children = (const struct uvcg_config_group_type*[]) { 3479 &uvcg_control_grp_type, 3480 &uvcg_streaming_grp_type, 3481 NULL, 3482 }, 3483}; 3484 3485int uvcg_attach_configfs(struct f_uvc_opts *opts) 3486{ 3487 int ret; 3488 3489 config_group_init_type_name(&opts->func_inst.group, uvc_func_type.name, 3490 &uvc_func_type.type); 3491 3492 ret = uvcg_config_create_children(&opts->func_inst.group, 3493 &uvc_func_type); 3494 if (ret < 0) 3495 config_group_put(&opts->func_inst.group); 3496 3497 return ret; 3498}