linux/drivers/media/video/uvc/uvc_ctrl.c
<<
>>
Prefs
   1/*
   2 *      uvc_ctrl.c  --  USB Video Class driver - Controls
   3 *
   4 *      Copyright (C) 2005-2009
   5 *          Laurent Pinchart (laurent.pinchart@skynet.be)
   6 *
   7 *      This program is free software; you can redistribute it and/or modify
   8 *      it under the terms of the GNU General Public License as published by
   9 *      the Free Software Foundation; either version 2 of the License, or
  10 *      (at your option) any later version.
  11 *
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/list.h>
  16#include <linux/module.h>
  17#include <linux/uaccess.h>
  18#include <linux/usb.h>
  19#include <linux/videodev2.h>
  20#include <linux/vmalloc.h>
  21#include <linux/wait.h>
  22#include <asm/atomic.h>
  23
  24#include "uvcvideo.h"
  25
  26#define UVC_CTRL_NDATA          2
  27#define UVC_CTRL_DATA_CURRENT   0
  28#define UVC_CTRL_DATA_BACKUP    1
  29
  30/* ------------------------------------------------------------------------
  31 * Controls
  32 */
  33
  34static struct uvc_control_info uvc_ctrls[] = {
  35        {
  36                .entity         = UVC_GUID_UVC_PROCESSING,
  37                .selector       = UVC_PU_BRIGHTNESS_CONTROL,
  38                .index          = 0,
  39                .size           = 2,
  40                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  41                                | UVC_CONTROL_RESTORE,
  42        },
  43        {
  44                .entity         = UVC_GUID_UVC_PROCESSING,
  45                .selector       = UVC_PU_CONTRAST_CONTROL,
  46                .index          = 1,
  47                .size           = 2,
  48                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  49                                | UVC_CONTROL_RESTORE,
  50        },
  51        {
  52                .entity         = UVC_GUID_UVC_PROCESSING,
  53                .selector       = UVC_PU_HUE_CONTROL,
  54                .index          = 2,
  55                .size           = 2,
  56                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  57                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
  58        },
  59        {
  60                .entity         = UVC_GUID_UVC_PROCESSING,
  61                .selector       = UVC_PU_SATURATION_CONTROL,
  62                .index          = 3,
  63                .size           = 2,
  64                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  65                                | UVC_CONTROL_RESTORE,
  66        },
  67        {
  68                .entity         = UVC_GUID_UVC_PROCESSING,
  69                .selector       = UVC_PU_SHARPNESS_CONTROL,
  70                .index          = 4,
  71                .size           = 2,
  72                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  73                                | UVC_CONTROL_RESTORE,
  74        },
  75        {
  76                .entity         = UVC_GUID_UVC_PROCESSING,
  77                .selector       = UVC_PU_GAMMA_CONTROL,
  78                .index          = 5,
  79                .size           = 2,
  80                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  81                                | UVC_CONTROL_RESTORE,
  82        },
  83        {
  84                .entity         = UVC_GUID_UVC_PROCESSING,
  85                .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
  86                .index          = 6,
  87                .size           = 2,
  88                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  89                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
  90        },
  91        {
  92                .entity         = UVC_GUID_UVC_PROCESSING,
  93                .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
  94                .index          = 7,
  95                .size           = 4,
  96                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
  97                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
  98        },
  99        {
 100                .entity         = UVC_GUID_UVC_PROCESSING,
 101                .selector       = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
 102                .index          = 8,
 103                .size           = 2,
 104                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 105                                | UVC_CONTROL_RESTORE,
 106        },
 107        {
 108                .entity         = UVC_GUID_UVC_PROCESSING,
 109                .selector       = UVC_PU_GAIN_CONTROL,
 110                .index          = 9,
 111                .size           = 2,
 112                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 113                                | UVC_CONTROL_RESTORE,
 114        },
 115        {
 116                .entity         = UVC_GUID_UVC_PROCESSING,
 117                .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
 118                .index          = 10,
 119                .size           = 1,
 120                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 121                                | UVC_CONTROL_RESTORE,
 122        },
 123        {
 124                .entity         = UVC_GUID_UVC_PROCESSING,
 125                .selector       = UVC_PU_HUE_AUTO_CONTROL,
 126                .index          = 11,
 127                .size           = 1,
 128                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 129                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
 130        },
 131        {
 132                .entity         = UVC_GUID_UVC_PROCESSING,
 133                .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
 134                .index          = 12,
 135                .size           = 1,
 136                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 137                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
 138        },
 139        {
 140                .entity         = UVC_GUID_UVC_PROCESSING,
 141                .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
 142                .index          = 13,
 143                .size           = 1,
 144                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 145                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
 146        },
 147        {
 148                .entity         = UVC_GUID_UVC_PROCESSING,
 149                .selector       = UVC_PU_DIGITAL_MULTIPLIER_CONTROL,
 150                .index          = 14,
 151                .size           = 2,
 152                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 153                                | UVC_CONTROL_RESTORE,
 154        },
 155        {
 156                .entity         = UVC_GUID_UVC_PROCESSING,
 157                .selector       = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
 158                .index          = 15,
 159                .size           = 2,
 160                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 161                                | UVC_CONTROL_RESTORE,
 162        },
 163        {
 164                .entity         = UVC_GUID_UVC_PROCESSING,
 165                .selector       = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL,
 166                .index          = 16,
 167                .size           = 1,
 168                .flags          = UVC_CONTROL_GET_CUR,
 169        },
 170        {
 171                .entity         = UVC_GUID_UVC_PROCESSING,
 172                .selector       = UVC_PU_ANALOG_LOCK_STATUS_CONTROL,
 173                .index          = 17,
 174                .size           = 1,
 175                .flags          = UVC_CONTROL_GET_CUR,
 176        },
 177        {
 178                .entity         = UVC_GUID_UVC_CAMERA,
 179                .selector       = UVC_CT_SCANNING_MODE_CONTROL,
 180                .index          = 0,
 181                .size           = 1,
 182                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 183                                | UVC_CONTROL_RESTORE,
 184        },
 185        {
 186                .entity         = UVC_GUID_UVC_CAMERA,
 187                .selector       = UVC_CT_AE_MODE_CONTROL,
 188                .index          = 1,
 189                .size           = 1,
 190                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 191                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES
 192                                | UVC_CONTROL_RESTORE,
 193        },
 194        {
 195                .entity         = UVC_GUID_UVC_CAMERA,
 196                .selector       = UVC_CT_AE_PRIORITY_CONTROL,
 197                .index          = 2,
 198                .size           = 1,
 199                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 200                                | UVC_CONTROL_RESTORE,
 201        },
 202        {
 203                .entity         = UVC_GUID_UVC_CAMERA,
 204                .selector       = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
 205                .index          = 3,
 206                .size           = 4,
 207                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 208                                | UVC_CONTROL_RESTORE,
 209        },
 210        {
 211                .entity         = UVC_GUID_UVC_CAMERA,
 212                .selector       = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL,
 213                .index          = 4,
 214                .size           = 1,
 215                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 216                                | UVC_CONTROL_RESTORE,
 217        },
 218        {
 219                .entity         = UVC_GUID_UVC_CAMERA,
 220                .selector       = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
 221                .index          = 5,
 222                .size           = 2,
 223                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 224                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 225        },
 226        {
 227                .entity         = UVC_GUID_UVC_CAMERA,
 228                .selector       = UVC_CT_FOCUS_RELATIVE_CONTROL,
 229                .index          = 6,
 230                .size           = 2,
 231                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 232                                | UVC_CONTROL_AUTO_UPDATE,
 233        },
 234        {
 235                .entity         = UVC_GUID_UVC_CAMERA,
 236                .selector       = UVC_CT_IRIS_ABSOLUTE_CONTROL,
 237                .index          = 7,
 238                .size           = 2,
 239                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 240                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 241        },
 242        {
 243                .entity         = UVC_GUID_UVC_CAMERA,
 244                .selector       = UVC_CT_IRIS_RELATIVE_CONTROL,
 245                .index          = 8,
 246                .size           = 1,
 247                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 248                                | UVC_CONTROL_AUTO_UPDATE,
 249        },
 250        {
 251                .entity         = UVC_GUID_UVC_CAMERA,
 252                .selector       = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
 253                .index          = 9,
 254                .size           = 2,
 255                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 256                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 257        },
 258        {
 259                .entity         = UVC_GUID_UVC_CAMERA,
 260                .selector       = UVC_CT_ZOOM_RELATIVE_CONTROL,
 261                .index          = 10,
 262                .size           = 3,
 263                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 264                                | UVC_CONTROL_AUTO_UPDATE,
 265        },
 266        {
 267                .entity         = UVC_GUID_UVC_CAMERA,
 268                .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
 269                .index          = 11,
 270                .size           = 8,
 271                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 272                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 273        },
 274        {
 275                .entity         = UVC_GUID_UVC_CAMERA,
 276                .selector       = UVC_CT_PANTILT_RELATIVE_CONTROL,
 277                .index          = 12,
 278                .size           = 4,
 279                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 280                                | UVC_CONTROL_AUTO_UPDATE,
 281        },
 282        {
 283                .entity         = UVC_GUID_UVC_CAMERA,
 284                .selector       = UVC_CT_ROLL_ABSOLUTE_CONTROL,
 285                .index          = 13,
 286                .size           = 2,
 287                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 288                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 289        },
 290        {
 291                .entity         = UVC_GUID_UVC_CAMERA,
 292                .selector       = UVC_CT_ROLL_RELATIVE_CONTROL,
 293                .index          = 14,
 294                .size           = 2,
 295                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
 296                                | UVC_CONTROL_AUTO_UPDATE,
 297        },
 298        {
 299                .entity         = UVC_GUID_UVC_CAMERA,
 300                .selector       = UVC_CT_FOCUS_AUTO_CONTROL,
 301                .index          = 17,
 302                .size           = 1,
 303                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 304                                | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
 305        },
 306        {
 307                .entity         = UVC_GUID_UVC_CAMERA,
 308                .selector       = UVC_CT_PRIVACY_CONTROL,
 309                .index          = 18,
 310                .size           = 1,
 311                .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
 312                                | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
 313        },
 314};
 315
 316static struct uvc_menu_info power_line_frequency_controls[] = {
 317        { 0, "Disabled" },
 318        { 1, "50 Hz" },
 319        { 2, "60 Hz" },
 320};
 321
 322static struct uvc_menu_info exposure_auto_controls[] = {
 323        { 2, "Auto Mode" },
 324        { 1, "Manual Mode" },
 325        { 4, "Shutter Priority Mode" },
 326        { 8, "Aperture Priority Mode" },
 327};
 328
 329static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
 330        __u8 query, const __u8 *data)
 331{
 332        __s8 zoom = (__s8)data[0];
 333
 334        switch (query) {
 335        case UVC_GET_CUR:
 336                return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
 337
 338        case UVC_GET_MIN:
 339        case UVC_GET_MAX:
 340        case UVC_GET_RES:
 341        case UVC_GET_DEF:
 342        default:
 343                return data[2];
 344        }
 345}
 346
 347static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
 348        __s32 value, __u8 *data)
 349{
 350        data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
 351        data[2] = min((int)abs(value), 0xff);
 352}
 353
 354static struct uvc_control_mapping uvc_ctrl_mappings[] = {
 355        {
 356                .id             = V4L2_CID_BRIGHTNESS,
 357                .name           = "Brightness",
 358                .entity         = UVC_GUID_UVC_PROCESSING,
 359                .selector       = UVC_PU_BRIGHTNESS_CONTROL,
 360                .size           = 16,
 361                .offset         = 0,
 362                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 363                .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
 364        },
 365        {
 366                .id             = V4L2_CID_CONTRAST,
 367                .name           = "Contrast",
 368                .entity         = UVC_GUID_UVC_PROCESSING,
 369                .selector       = UVC_PU_CONTRAST_CONTROL,
 370                .size           = 16,
 371                .offset         = 0,
 372                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 373                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 374        },
 375        {
 376                .id             = V4L2_CID_HUE,
 377                .name           = "Hue",
 378                .entity         = UVC_GUID_UVC_PROCESSING,
 379                .selector       = UVC_PU_HUE_CONTROL,
 380                .size           = 16,
 381                .offset         = 0,
 382                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 383                .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
 384        },
 385        {
 386                .id             = V4L2_CID_SATURATION,
 387                .name           = "Saturation",
 388                .entity         = UVC_GUID_UVC_PROCESSING,
 389                .selector       = UVC_PU_SATURATION_CONTROL,
 390                .size           = 16,
 391                .offset         = 0,
 392                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 393                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 394        },
 395        {
 396                .id             = V4L2_CID_SHARPNESS,
 397                .name           = "Sharpness",
 398                .entity         = UVC_GUID_UVC_PROCESSING,
 399                .selector       = UVC_PU_SHARPNESS_CONTROL,
 400                .size           = 16,
 401                .offset         = 0,
 402                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 403                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 404        },
 405        {
 406                .id             = V4L2_CID_GAMMA,
 407                .name           = "Gamma",
 408                .entity         = UVC_GUID_UVC_PROCESSING,
 409                .selector       = UVC_PU_GAMMA_CONTROL,
 410                .size           = 16,
 411                .offset         = 0,
 412                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 413                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 414        },
 415        {
 416                .id             = V4L2_CID_BACKLIGHT_COMPENSATION,
 417                .name           = "Backlight Compensation",
 418                .entity         = UVC_GUID_UVC_PROCESSING,
 419                .selector       = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
 420                .size           = 16,
 421                .offset         = 0,
 422                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 423                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 424        },
 425        {
 426                .id             = V4L2_CID_GAIN,
 427                .name           = "Gain",
 428                .entity         = UVC_GUID_UVC_PROCESSING,
 429                .selector       = UVC_PU_GAIN_CONTROL,
 430                .size           = 16,
 431                .offset         = 0,
 432                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 433                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 434        },
 435        {
 436                .id             = V4L2_CID_POWER_LINE_FREQUENCY,
 437                .name           = "Power Line Frequency",
 438                .entity         = UVC_GUID_UVC_PROCESSING,
 439                .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
 440                .size           = 2,
 441                .offset         = 0,
 442                .v4l2_type      = V4L2_CTRL_TYPE_MENU,
 443                .data_type      = UVC_CTRL_DATA_TYPE_ENUM,
 444                .menu_info      = power_line_frequency_controls,
 445                .menu_count     = ARRAY_SIZE(power_line_frequency_controls),
 446        },
 447        {
 448                .id             = V4L2_CID_HUE_AUTO,
 449                .name           = "Hue, Auto",
 450                .entity         = UVC_GUID_UVC_PROCESSING,
 451                .selector       = UVC_PU_HUE_AUTO_CONTROL,
 452                .size           = 1,
 453                .offset         = 0,
 454                .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
 455                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
 456        },
 457        {
 458                .id             = V4L2_CID_EXPOSURE_AUTO,
 459                .name           = "Exposure, Auto",
 460                .entity         = UVC_GUID_UVC_CAMERA,
 461                .selector       = UVC_CT_AE_MODE_CONTROL,
 462                .size           = 4,
 463                .offset         = 0,
 464                .v4l2_type      = V4L2_CTRL_TYPE_MENU,
 465                .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
 466                .menu_info      = exposure_auto_controls,
 467                .menu_count     = ARRAY_SIZE(exposure_auto_controls),
 468        },
 469        {
 470                .id             = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
 471                .name           = "Exposure, Auto Priority",
 472                .entity         = UVC_GUID_UVC_CAMERA,
 473                .selector       = UVC_CT_AE_PRIORITY_CONTROL,
 474                .size           = 1,
 475                .offset         = 0,
 476                .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
 477                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
 478        },
 479        {
 480                .id             = V4L2_CID_EXPOSURE_ABSOLUTE,
 481                .name           = "Exposure (Absolute)",
 482                .entity         = UVC_GUID_UVC_CAMERA,
 483                .selector       = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
 484                .size           = 32,
 485                .offset         = 0,
 486                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 487                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 488        },
 489        {
 490                .id             = V4L2_CID_AUTO_WHITE_BALANCE,
 491                .name           = "White Balance Temperature, Auto",
 492                .entity         = UVC_GUID_UVC_PROCESSING,
 493                .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
 494                .size           = 1,
 495                .offset         = 0,
 496                .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
 497                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
 498        },
 499        {
 500                .id             = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
 501                .name           = "White Balance Temperature",
 502                .entity         = UVC_GUID_UVC_PROCESSING,
 503                .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
 504                .size           = 16,
 505                .offset         = 0,
 506                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 507                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 508        },
 509        {
 510                .id             = V4L2_CID_AUTO_WHITE_BALANCE,
 511                .name           = "White Balance Component, Auto",
 512                .entity         = UVC_GUID_UVC_PROCESSING,
 513                .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
 514                .size           = 1,
 515                .offset         = 0,
 516                .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
 517                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
 518        },
 519        {
 520                .id             = V4L2_CID_BLUE_BALANCE,
 521                .name           = "White Balance Blue Component",
 522                .entity         = UVC_GUID_UVC_PROCESSING,
 523                .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
 524                .size           = 16,
 525                .offset         = 0,
 526                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 527                .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
 528        },
 529        {
 530                .id             = V4L2_CID_RED_BALANCE,
 531                .name           = "White Balance Red Component",
 532                .entity         = UVC_GUID_UVC_PROCESSING,
 533                .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
 534                .size           = 16,
 535                .offset         = 16,
 536                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 537                .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
 538        },
 539        {
 540                .id             = V4L2_CID_FOCUS_ABSOLUTE,
 541                .name           = "Focus (absolute)",
 542                .entity         = UVC_GUID_UVC_CAMERA,
 543                .selector       = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
 544                .size           = 16,
 545                .offset         = 0,
 546                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 547                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 548        },
 549        {
 550                .id             = V4L2_CID_FOCUS_AUTO,
 551                .name           = "Focus, Auto",
 552                .entity         = UVC_GUID_UVC_CAMERA,
 553                .selector       = UVC_CT_FOCUS_AUTO_CONTROL,
 554                .size           = 1,
 555                .offset         = 0,
 556                .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
 557                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
 558        },
 559        {
 560                .id             = V4L2_CID_ZOOM_ABSOLUTE,
 561                .name           = "Zoom, Absolute",
 562                .entity         = UVC_GUID_UVC_CAMERA,
 563                .selector       = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
 564                .size           = 16,
 565                .offset         = 0,
 566                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 567                .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
 568        },
 569        {
 570                .id             = V4L2_CID_ZOOM_CONTINUOUS,
 571                .name           = "Zoom, Continuous",
 572                .entity         = UVC_GUID_UVC_CAMERA,
 573                .selector       = UVC_CT_ZOOM_RELATIVE_CONTROL,
 574                .size           = 0,
 575                .offset         = 0,
 576                .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
 577                .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
 578                .get            = uvc_ctrl_get_zoom,
 579                .set            = uvc_ctrl_set_zoom,
 580        },
 581        {
 582                .id             = V4L2_CID_PRIVACY,
 583                .name           = "Privacy",
 584                .entity         = UVC_GUID_UVC_CAMERA,
 585                .selector       = UVC_CT_PRIVACY_CONTROL,
 586                .size           = 1,
 587                .offset         = 0,
 588                .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
 589                .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
 590        },
 591};
 592
 593/* ------------------------------------------------------------------------
 594 * Utility functions
 595 */
 596
 597static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
 598{
 599        return ctrl->data + id * ctrl->info->size;
 600}
 601
 602static inline int uvc_test_bit(const __u8 *data, int bit)
 603{
 604        return (data[bit >> 3] >> (bit & 7)) & 1;
 605}
 606
 607static inline void uvc_clear_bit(__u8 *data, int bit)
 608{
 609        data[bit >> 3] &= ~(1 << (bit & 7));
 610}
 611
 612/* Extract the bit string specified by mapping->offset and mapping->size
 613 * from the little-endian data stored at 'data' and return the result as
 614 * a signed 32bit integer. Sign extension will be performed if the mapping
 615 * references a signed data type.
 616 */
 617static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
 618        __u8 query, const __u8 *data)
 619{
 620        int bits = mapping->size;
 621        int offset = mapping->offset;
 622        __s32 value = 0;
 623        __u8 mask;
 624
 625        data += offset / 8;
 626        offset &= 7;
 627        mask = ((1LL << bits) - 1) << offset;
 628
 629        for (; bits > 0; data++) {
 630                __u8 byte = *data & mask;
 631                value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
 632                bits -= 8 - (offset > 0 ? offset : 0);
 633                offset -= 8;
 634                mask = (1 << bits) - 1;
 635        }
 636
 637        /* Sign-extend the value if needed. */
 638        if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
 639                value |= -(value & (1 << (mapping->size - 1)));
 640
 641        return value;
 642}
 643
 644/* Set the bit string specified by mapping->offset and mapping->size
 645 * in the little-endian data stored at 'data' to the value 'value'.
 646 */
 647static void uvc_set_le_value(struct uvc_control_mapping *mapping,
 648        __s32 value, __u8 *data)
 649{
 650        int bits = mapping->size;
 651        int offset = mapping->offset;
 652        __u8 mask;
 653
 654        data += offset / 8;
 655        offset &= 7;
 656
 657        for (; bits > 0; data++) {
 658                mask = ((1LL << bits) - 1) << offset;
 659                *data = (*data & ~mask) | ((value << offset) & mask);
 660                value >>= offset ? offset : 8;
 661                bits -= 8 - offset;
 662                offset = 0;
 663        }
 664}
 665
 666/* ------------------------------------------------------------------------
 667 * Terminal and unit management
 668 */
 669
 670static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
 671static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA;
 672static const __u8 uvc_media_transport_input_guid[16] =
 673        UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
 674
 675static int uvc_entity_match_guid(struct uvc_entity *entity, __u8 guid[16])
 676{
 677        switch (UVC_ENTITY_TYPE(entity)) {
 678        case UVC_ITT_CAMERA:
 679                return memcmp(uvc_camera_guid, guid, 16) == 0;
 680
 681        case UVC_ITT_MEDIA_TRANSPORT_INPUT:
 682                return memcmp(uvc_media_transport_input_guid, guid, 16) == 0;
 683
 684        case UVC_VC_PROCESSING_UNIT:
 685                return memcmp(uvc_processing_guid, guid, 16) == 0;
 686
 687        case UVC_VC_EXTENSION_UNIT:
 688                return memcmp(entity->extension.guidExtensionCode,
 689                              guid, 16) == 0;
 690
 691        default:
 692                return 0;
 693        }
 694}
 695
 696/* ------------------------------------------------------------------------
 697 * UVC Controls
 698 */
 699
 700static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
 701        struct uvc_control_mapping **mapping, struct uvc_control **control,
 702        int next)
 703{
 704        struct uvc_control *ctrl;
 705        struct uvc_control_mapping *map;
 706        unsigned int i;
 707
 708        if (entity == NULL)
 709                return;
 710
 711        for (i = 0; i < entity->ncontrols; ++i) {
 712                ctrl = &entity->controls[i];
 713                if (ctrl->info == NULL)
 714                        continue;
 715
 716                list_for_each_entry(map, &ctrl->info->mappings, list) {
 717                        if ((map->id == v4l2_id) && !next) {
 718                                *control = ctrl;
 719                                *mapping = map;
 720                                return;
 721                        }
 722
 723                        if ((*mapping == NULL || (*mapping)->id > map->id) &&
 724                            (map->id > v4l2_id) && next) {
 725                                *control = ctrl;
 726                                *mapping = map;
 727                        }
 728                }
 729        }
 730}
 731
 732struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
 733        __u32 v4l2_id, struct uvc_control_mapping **mapping)
 734{
 735        struct uvc_control *ctrl = NULL;
 736        struct uvc_entity *entity;
 737        int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL;
 738
 739        *mapping = NULL;
 740
 741        /* Mask the query flags. */
 742        v4l2_id &= V4L2_CTRL_ID_MASK;
 743
 744        /* Find the control. */
 745        __uvc_find_control(chain->processing, v4l2_id, mapping, &ctrl, next);
 746        if (ctrl && !next)
 747                return ctrl;
 748
 749        list_for_each_entry(entity, &chain->iterms, chain) {
 750                __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
 751                if (ctrl && !next)
 752                        return ctrl;
 753        }
 754
 755        list_for_each_entry(entity, &chain->extensions, chain) {
 756                __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
 757                if (ctrl && !next)
 758                        return ctrl;
 759        }
 760
 761        if (ctrl == NULL && !next)
 762                uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n",
 763                                v4l2_id);
 764
 765        return ctrl;
 766}
 767
 768int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
 769        struct v4l2_queryctrl *v4l2_ctrl)
 770{
 771        struct uvc_control *ctrl;
 772        struct uvc_control_mapping *mapping;
 773        struct uvc_menu_info *menu;
 774        unsigned int i;
 775        __u8 *data;
 776        int ret;
 777
 778        ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
 779        if (ctrl == NULL)
 780                return -EINVAL;
 781
 782        data = kmalloc(ctrl->info->size, GFP_KERNEL);
 783        if (data == NULL)
 784                return -ENOMEM;
 785
 786        memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
 787        v4l2_ctrl->id = mapping->id;
 788        v4l2_ctrl->type = mapping->v4l2_type;
 789        strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
 790        v4l2_ctrl->flags = 0;
 791
 792        if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR))
 793                v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 794
 795        if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
 796                ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id,
 797                                     chain->dev->intfnum, ctrl->info->selector,
 798                                     data, ctrl->info->size);
 799                if (ret < 0)
 800                        goto out;
 801                v4l2_ctrl->default_value =
 802                        mapping->get(mapping, UVC_GET_DEF, data);
 803        }
 804
 805        switch (mapping->v4l2_type) {
 806        case V4L2_CTRL_TYPE_MENU:
 807                v4l2_ctrl->minimum = 0;
 808                v4l2_ctrl->maximum = mapping->menu_count - 1;
 809                v4l2_ctrl->step = 1;
 810
 811                menu = mapping->menu_info;
 812                for (i = 0; i < mapping->menu_count; ++i, ++menu) {
 813                        if (menu->value == v4l2_ctrl->default_value) {
 814                                v4l2_ctrl->default_value = i;
 815                                break;
 816                        }
 817                }
 818
 819                ret = 0;
 820                goto out;
 821
 822        case V4L2_CTRL_TYPE_BOOLEAN:
 823                v4l2_ctrl->minimum = 0;
 824                v4l2_ctrl->maximum = 1;
 825                v4l2_ctrl->step = 1;
 826                ret = 0;
 827                goto out;
 828
 829        default:
 830                break;
 831        }
 832
 833        if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
 834                ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id,
 835                                     chain->dev->intfnum, ctrl->info->selector,
 836                                     data, ctrl->info->size);
 837                if (ret < 0)
 838                        goto out;
 839                v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN, data);
 840        }
 841        if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
 842                ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
 843                                     chain->dev->intfnum, ctrl->info->selector,
 844                                     data, ctrl->info->size);
 845                if (ret < 0)
 846                        goto out;
 847                v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX, data);
 848        }
 849        if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
 850                ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
 851                                     chain->dev->intfnum, ctrl->info->selector,
 852                                     data, ctrl->info->size);
 853                if (ret < 0)
 854                        goto out;
 855                v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES, data);
 856        }
 857
 858        ret = 0;
 859out:
 860        kfree(data);
 861        return ret;
 862}
 863
 864
 865/* --------------------------------------------------------------------------
 866 * Control transactions
 867 *
 868 * To make extended set operations as atomic as the hardware allows, controls
 869 * are handled using begin/commit/rollback operations.
 870 *
 871 * At the beginning of a set request, uvc_ctrl_begin should be called to
 872 * initialize the request. This function acquires the control lock.
 873 *
 874 * When setting a control, the new value is stored in the control data field
 875 * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for
 876 * later processing. If the UVC and V4L2 control sizes differ, the current
 877 * value is loaded from the hardware before storing the new value in the data
 878 * field.
 879 *
 880 * After processing all controls in the transaction, uvc_ctrl_commit or
 881 * uvc_ctrl_rollback must be called to apply the pending changes to the
 882 * hardware or revert them. When applying changes, all controls marked as
 883 * dirty will be modified in the UVC device, and the dirty flag will be
 884 * cleared. When reverting controls, the control data field
 885 * UVC_CTRL_DATA_CURRENT is reverted to its previous value
 886 * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
 887 * control lock.
 888 */
 889int uvc_ctrl_begin(struct uvc_video_chain *chain)
 890{
 891        return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0;
 892}
 893
 894static int uvc_ctrl_commit_entity(struct uvc_device *dev,
 895        struct uvc_entity *entity, int rollback)
 896{
 897        struct uvc_control *ctrl;
 898        unsigned int i;
 899        int ret;
 900
 901        if (entity == NULL)
 902                return 0;
 903
 904        for (i = 0; i < entity->ncontrols; ++i) {
 905                ctrl = &entity->controls[i];
 906                if (ctrl->info == NULL)
 907                        continue;
 908
 909                /* Reset the loaded flag for auto-update controls that were
 910                 * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent
 911                 * uvc_ctrl_get from using the cached value.
 912                 */
 913                if (ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE)
 914                        ctrl->loaded = 0;
 915
 916                if (!ctrl->dirty)
 917                        continue;
 918
 919                if (!rollback)
 920                        ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id,
 921                                dev->intfnum, ctrl->info->selector,
 922                                uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 923                                ctrl->info->size);
 924                else
 925                        ret = 0;
 926
 927                if (rollback || ret < 0)
 928                        memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 929                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
 930                               ctrl->info->size);
 931
 932                ctrl->dirty = 0;
 933
 934                if (ret < 0)
 935                        return ret;
 936        }
 937
 938        return 0;
 939}
 940
 941int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback)
 942{
 943        struct uvc_entity *entity;
 944        int ret = 0;
 945
 946        /* Find the control. */
 947        ret = uvc_ctrl_commit_entity(chain->dev, chain->processing, rollback);
 948        if (ret < 0)
 949                goto done;
 950
 951        list_for_each_entry(entity, &chain->iterms, chain) {
 952                ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
 953                if (ret < 0)
 954                        goto done;
 955        }
 956
 957        list_for_each_entry(entity, &chain->extensions, chain) {
 958                ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
 959                if (ret < 0)
 960                        goto done;
 961        }
 962
 963done:
 964        mutex_unlock(&chain->ctrl_mutex);
 965        return ret;
 966}
 967
 968int uvc_ctrl_get(struct uvc_video_chain *chain,
 969        struct v4l2_ext_control *xctrl)
 970{
 971        struct uvc_control *ctrl;
 972        struct uvc_control_mapping *mapping;
 973        struct uvc_menu_info *menu;
 974        unsigned int i;
 975        int ret;
 976
 977        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
 978        if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0)
 979                return -EINVAL;
 980
 981        if (!ctrl->loaded) {
 982                ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
 983                                chain->dev->intfnum, ctrl->info->selector,
 984                                uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
 985                                ctrl->info->size);
 986                if (ret < 0)
 987                        return ret;
 988
 989                ctrl->loaded = 1;
 990        }
 991
 992        xctrl->value = mapping->get(mapping, UVC_GET_CUR,
 993                uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 994
 995        if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
 996                menu = mapping->menu_info;
 997                for (i = 0; i < mapping->menu_count; ++i, ++menu) {
 998                        if (menu->value == xctrl->value) {
 999                                xctrl->value = i;
1000                                break;
1001                        }
1002                }
1003        }
1004
1005        return 0;
1006}
1007
1008int uvc_ctrl_set(struct uvc_video_chain *chain,
1009        struct v4l2_ext_control *xctrl)
1010{
1011        struct uvc_control *ctrl;
1012        struct uvc_control_mapping *mapping;
1013        s32 value = xctrl->value;
1014        int ret;
1015
1016        ctrl = uvc_find_control(chain, xctrl->id, &mapping);
1017        if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0)
1018                return -EINVAL;
1019
1020        if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
1021                if (value < 0 || value >= mapping->menu_count)
1022                        return -EINVAL;
1023                value = mapping->menu_info[value].value;
1024        }
1025
1026        if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) {
1027                if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) {
1028                        memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
1029                                0, ctrl->info->size);
1030                } else {
1031                        ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
1032                                ctrl->entity->id, chain->dev->intfnum,
1033                                ctrl->info->selector,
1034                                uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
1035                                ctrl->info->size);
1036                        if (ret < 0)
1037                                return ret;
1038                }
1039
1040                ctrl->loaded = 1;
1041        }
1042
1043        if (!ctrl->dirty) {
1044                memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
1045                       uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
1046                       ctrl->info->size);
1047        }
1048
1049        mapping->set(mapping, value,
1050                uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
1051
1052        ctrl->dirty = 1;
1053        ctrl->modified = 1;
1054        return 0;
1055}
1056
1057/* --------------------------------------------------------------------------
1058 * Dynamic controls
1059 */
1060
1061int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
1062        struct uvc_xu_control *xctrl, int set)
1063{
1064        struct uvc_entity *entity;
1065        struct uvc_control *ctrl = NULL;
1066        unsigned int i, found = 0;
1067        __u8 *data;
1068        int ret;
1069
1070        /* Find the extension unit. */
1071        list_for_each_entry(entity, &chain->extensions, chain) {
1072                if (entity->id == xctrl->unit)
1073                        break;
1074        }
1075
1076        if (entity->id != xctrl->unit) {
1077                uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n",
1078                        xctrl->unit);
1079                return -EINVAL;
1080        }
1081
1082        /* Find the control. */
1083        for (i = 0; i < entity->ncontrols; ++i) {
1084                ctrl = &entity->controls[i];
1085                if (ctrl->info == NULL)
1086                        continue;
1087
1088                if (ctrl->info->selector == xctrl->selector) {
1089                        found = 1;
1090                        break;
1091                }
1092        }
1093
1094        if (!found) {
1095                uvc_trace(UVC_TRACE_CONTROL,
1096                        "Control " UVC_GUID_FORMAT "/%u not found.\n",
1097                        UVC_GUID_ARGS(entity->extension.guidExtensionCode),
1098                        xctrl->selector);
1099                return -EINVAL;
1100        }
1101
1102        /* Validate control data size. */
1103        if (ctrl->info->size != xctrl->size)
1104                return -EINVAL;
1105
1106        if ((set && !(ctrl->info->flags & UVC_CONTROL_SET_CUR)) ||
1107            (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR)))
1108                return -EINVAL;
1109
1110        if (mutex_lock_interruptible(&chain->ctrl_mutex))
1111                return -ERESTARTSYS;
1112
1113        memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
1114               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
1115               xctrl->size);
1116        data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);
1117
1118        if (set && copy_from_user(data, xctrl->data, xctrl->size)) {
1119                ret = -EFAULT;
1120                goto out;
1121        }
1122
1123        ret = uvc_query_ctrl(chain->dev, set ? UVC_SET_CUR : UVC_GET_CUR,
1124                             xctrl->unit, chain->dev->intfnum, xctrl->selector,
1125                             data, xctrl->size);
1126        if (ret < 0)
1127                goto out;
1128
1129        if (!set && copy_to_user(xctrl->data, data, xctrl->size)) {
1130                ret = -EFAULT;
1131                goto out;
1132        }
1133
1134out:
1135        if (ret)
1136                memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
1137                       uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
1138                       xctrl->size);
1139
1140        mutex_unlock(&chain->ctrl_mutex);
1141        return ret;
1142}
1143
1144/* --------------------------------------------------------------------------
1145 * Suspend/resume
1146 */
1147
1148/*
1149 * Restore control values after resume, skipping controls that haven't been
1150 * changed.
1151 *
1152 * TODO
1153 * - Don't restore modified controls that are back to their default value.
1154 * - Handle restore order (Auto-Exposure Mode should be restored before
1155 *   Exposure Time).
1156 */
1157int uvc_ctrl_resume_device(struct uvc_device *dev)
1158{
1159        struct uvc_control *ctrl;
1160        struct uvc_entity *entity;
1161        unsigned int i;
1162        int ret;
1163
1164        /* Walk the entities list and restore controls when possible. */
1165        list_for_each_entry(entity, &dev->entities, list) {
1166
1167                for (i = 0; i < entity->ncontrols; ++i) {
1168                        ctrl = &entity->controls[i];
1169
1170                        if (ctrl->info == NULL || !ctrl->modified ||
1171                            (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0)
1172                                continue;
1173
1174                        printk(KERN_INFO "restoring control " UVC_GUID_FORMAT
1175                                "/%u/%u\n", UVC_GUID_ARGS(ctrl->info->entity),
1176                                ctrl->info->index, ctrl->info->selector);
1177                        ctrl->dirty = 1;
1178                }
1179
1180                ret = uvc_ctrl_commit_entity(dev, entity, 0);
1181                if (ret < 0)
1182                        return ret;
1183        }
1184
1185        return 0;
1186}
1187
1188/* --------------------------------------------------------------------------
1189 * Control and mapping handling
1190 */
1191
1192static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
1193        struct uvc_control_info *info)
1194{
1195        struct uvc_entity *entity;
1196        struct uvc_control *ctrl = NULL;
1197        int ret, found = 0;
1198        unsigned int i;
1199
1200        list_for_each_entry(entity, &dev->entities, list) {
1201                if (!uvc_entity_match_guid(entity, info->entity))
1202                        continue;
1203
1204                for (i = 0; i < entity->ncontrols; ++i) {
1205                        ctrl = &entity->controls[i];
1206                        if (ctrl->index == info->index) {
1207                                found = 1;
1208                                break;
1209                        }
1210                }
1211
1212                if (found)
1213                        break;
1214        }
1215
1216        if (!found)
1217                return;
1218
1219        if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
1220                /* Check if the device control information and length match
1221                 * the user supplied information.
1222                 */
1223                __u32 flags;
1224                __le16 size;
1225                __u8 inf;
1226
1227                ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id,
1228                        dev->intfnum, info->selector, (__u8 *)&size, 2);
1229                if (ret < 0) {
1230                        uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on "
1231                                "control " UVC_GUID_FORMAT "/%u (%d).\n",
1232                                UVC_GUID_ARGS(info->entity), info->selector,
1233                                ret);
1234                        return;
1235                }
1236
1237                if (info->size != le16_to_cpu(size)) {
1238                        uvc_trace(UVC_TRACE_CONTROL, "Control " UVC_GUID_FORMAT
1239                                "/%u size doesn't match user supplied "
1240                                "value.\n", UVC_GUID_ARGS(info->entity),
1241                                info->selector);
1242                        return;
1243                }
1244
1245                ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id,
1246                        dev->intfnum, info->selector, &inf, 1);
1247                if (ret < 0) {
1248                        uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on "
1249                                "control " UVC_GUID_FORMAT "/%u (%d).\n",
1250                                UVC_GUID_ARGS(info->entity), info->selector,
1251                                ret);
1252                        return;
1253                }
1254
1255                flags = info->flags;
1256                if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) ||
1257                    ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) {
1258                        uvc_trace(UVC_TRACE_CONTROL, "Control "
1259                                UVC_GUID_FORMAT "/%u flags don't match "
1260                                "supported operations.\n",
1261                                UVC_GUID_ARGS(info->entity), info->selector);
1262                        return;
1263                }
1264        }
1265
1266        ctrl->info = info;
1267        ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL);
1268        uvc_trace(UVC_TRACE_CONTROL, "Added control " UVC_GUID_FORMAT "/%u "
1269                "to device %s entity %u\n", UVC_GUID_ARGS(ctrl->info->entity),
1270                ctrl->info->selector, dev->udev->devpath, entity->id);
1271}
1272
1273/*
1274 * Add an item to the UVC control information list, and instantiate a control
1275 * structure for each device that supports the control.
1276 */
1277int uvc_ctrl_add_info(struct uvc_control_info *info)
1278{
1279        struct uvc_control_info *ctrl;
1280        struct uvc_device *dev;
1281        int ret = 0;
1282
1283        /* Find matching controls by walking the devices, entities and
1284         * controls list.
1285         */
1286        mutex_lock(&uvc_driver.ctrl_mutex);
1287
1288        /* First check if the list contains a control matching the new one.
1289         * Bail out if it does.
1290         */
1291        list_for_each_entry(ctrl, &uvc_driver.controls, list) {
1292                if (memcmp(ctrl->entity, info->entity, 16))
1293                        continue;
1294
1295                if (ctrl->selector == info->selector) {
1296                        uvc_trace(UVC_TRACE_CONTROL, "Control "
1297                                UVC_GUID_FORMAT "/%u is already defined.\n",
1298                                UVC_GUID_ARGS(info->entity), info->selector);
1299                        ret = -EEXIST;
1300                        goto end;
1301                }
1302                if (ctrl->index == info->index) {
1303                        uvc_trace(UVC_TRACE_CONTROL, "Control "
1304                                UVC_GUID_FORMAT "/%u would overwrite index "
1305                                "%d.\n", UVC_GUID_ARGS(info->entity),
1306                                info->selector, info->index);
1307                        ret = -EEXIST;
1308                        goto end;
1309                }
1310        }
1311
1312        list_for_each_entry(dev, &uvc_driver.devices, list)
1313                uvc_ctrl_add_ctrl(dev, info);
1314
1315        INIT_LIST_HEAD(&info->mappings);
1316        list_add_tail(&info->list, &uvc_driver.controls);
1317end:
1318        mutex_unlock(&uvc_driver.ctrl_mutex);
1319        return ret;
1320}
1321
1322int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping)
1323{
1324        struct uvc_control_info *info;
1325        struct uvc_control_mapping *map;
1326        int ret = -EINVAL;
1327
1328        if (mapping->get == NULL)
1329                mapping->get = uvc_get_le_value;
1330        if (mapping->set == NULL)
1331                mapping->set = uvc_set_le_value;
1332
1333        if (mapping->id & ~V4L2_CTRL_ID_MASK) {
1334                uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with "
1335                        "invalid control id 0x%08x\n", mapping->name,
1336                        mapping->id);
1337                return -EINVAL;
1338        }
1339
1340        mutex_lock(&uvc_driver.ctrl_mutex);
1341        list_for_each_entry(info, &uvc_driver.controls, list) {
1342                if (memcmp(info->entity, mapping->entity, 16) ||
1343                        info->selector != mapping->selector)
1344                        continue;
1345
1346                if (info->size * 8 < mapping->size + mapping->offset) {
1347                        uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' would "
1348                                "overflow control " UVC_GUID_FORMAT "/%u\n",
1349                                mapping->name, UVC_GUID_ARGS(info->entity),
1350                                info->selector);
1351                        ret = -EOVERFLOW;
1352                        goto end;
1353                }
1354
1355                /* Check if the list contains a mapping matching the new one.
1356                 * Bail out if it does.
1357                 */
1358                list_for_each_entry(map, &info->mappings, list) {
1359                        if (map->id == mapping->id) {
1360                                uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' is "
1361                                        "already defined.\n", mapping->name);
1362                                ret = -EEXIST;
1363                                goto end;
1364                        }
1365                }
1366
1367                mapping->ctrl = info;
1368                list_add_tail(&mapping->list, &info->mappings);
1369                uvc_trace(UVC_TRACE_CONTROL, "Adding mapping %s to control "
1370                        UVC_GUID_FORMAT "/%u.\n", mapping->name,
1371                        UVC_GUID_ARGS(info->entity), info->selector);
1372
1373                ret = 0;
1374                break;
1375        }
1376end:
1377        mutex_unlock(&uvc_driver.ctrl_mutex);
1378        return ret;
1379}
1380
1381/*
1382 * Prune an entity of its bogus controls using a blacklist. Bogus controls
1383 * are currently the ones that crash the camera or unconditionally return an
1384 * error when queried.
1385 */
1386static void
1387uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity)
1388{
1389        static const struct {
1390                struct usb_device_id id;
1391                u8 index;
1392        } blacklist[] = {
1393                { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
1394                { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
1395        };
1396
1397        u8 *controls;
1398        unsigned int size;
1399        unsigned int i;
1400
1401        if (UVC_ENTITY_TYPE(entity) != UVC_VC_PROCESSING_UNIT)
1402                return;
1403
1404        controls = entity->processing.bmControls;
1405        size = entity->processing.bControlSize;
1406
1407        for (i = 0; i < ARRAY_SIZE(blacklist); ++i) {
1408                if (!usb_match_id(dev->intf, &blacklist[i].id))
1409                        continue;
1410
1411                if (blacklist[i].index >= 8 * size ||
1412                    !uvc_test_bit(controls, blacklist[i].index))
1413                        continue;
1414
1415                uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
1416                        "removing it.\n", entity->id, blacklist[i].index);
1417
1418                uvc_clear_bit(controls, blacklist[i].index);
1419        }
1420}
1421
1422/*
1423 * Initialize device controls.
1424 */
1425int uvc_ctrl_init_device(struct uvc_device *dev)
1426{
1427        struct uvc_control_info *info;
1428        struct uvc_control *ctrl;
1429        struct uvc_entity *entity;
1430        unsigned int i;
1431
1432        /* Walk the entities list and instantiate controls */
1433        list_for_each_entry(entity, &dev->entities, list) {
1434                unsigned int bControlSize = 0, ncontrols = 0;
1435                __u8 *bmControls = NULL;
1436
1437                if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
1438                        bmControls = entity->extension.bmControls;
1439                        bControlSize = entity->extension.bControlSize;
1440                } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) {
1441                        bmControls = entity->processing.bmControls;
1442                        bControlSize = entity->processing.bControlSize;
1443                } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) {
1444                        bmControls = entity->camera.bmControls;
1445                        bControlSize = entity->camera.bControlSize;
1446                }
1447
1448                uvc_ctrl_prune_entity(dev, entity);
1449
1450                for (i = 0; i < bControlSize; ++i)
1451                        ncontrols += hweight8(bmControls[i]);
1452
1453                if (ncontrols == 0)
1454                        continue;
1455
1456                entity->controls = kzalloc(ncontrols*sizeof *ctrl, GFP_KERNEL);
1457                if (entity->controls == NULL)
1458                        return -ENOMEM;
1459
1460                entity->ncontrols = ncontrols;
1461
1462                ctrl = entity->controls;
1463                for (i = 0; i < bControlSize * 8; ++i) {
1464                        if (uvc_test_bit(bmControls, i) == 0)
1465                                continue;
1466
1467                        ctrl->entity = entity;
1468                        ctrl->index = i;
1469                        ctrl++;
1470                }
1471        }
1472
1473        /* Walk the controls info list and associate them with the device
1474         * controls, then add the device to the global device list. This has
1475         * to be done while holding the controls lock, to make sure
1476         * uvc_ctrl_add_info() will not get called in-between.
1477         */
1478        mutex_lock(&uvc_driver.ctrl_mutex);
1479        list_for_each_entry(info, &uvc_driver.controls, list)
1480                uvc_ctrl_add_ctrl(dev, info);
1481
1482        list_add_tail(&dev->list, &uvc_driver.devices);
1483        mutex_unlock(&uvc_driver.ctrl_mutex);
1484
1485        return 0;
1486}
1487
1488/*
1489 * Cleanup device controls.
1490 */
1491void uvc_ctrl_cleanup_device(struct uvc_device *dev)
1492{
1493        struct uvc_entity *entity;
1494        unsigned int i;
1495
1496        /* Remove the device from the global devices list */
1497        mutex_lock(&uvc_driver.ctrl_mutex);
1498        if (dev->list.next != NULL)
1499                list_del(&dev->list);
1500        mutex_unlock(&uvc_driver.ctrl_mutex);
1501
1502        list_for_each_entry(entity, &dev->entities, list) {
1503                for (i = 0; i < entity->ncontrols; ++i)
1504                        kfree(entity->controls[i].data);
1505
1506                kfree(entity->controls);
1507        }
1508}
1509
1510void uvc_ctrl_init(void)
1511{
1512        struct uvc_control_info *ctrl = uvc_ctrls;
1513        struct uvc_control_info *cend = ctrl + ARRAY_SIZE(uvc_ctrls);
1514        struct uvc_control_mapping *mapping = uvc_ctrl_mappings;
1515        struct uvc_control_mapping *mend =
1516                mapping + ARRAY_SIZE(uvc_ctrl_mappings);
1517
1518        for (; ctrl < cend; ++ctrl)
1519                uvc_ctrl_add_info(ctrl);
1520
1521        for (; mapping < mend; ++mapping)
1522                uvc_ctrl_add_mapping(mapping);
1523}
1524
1525