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