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