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