root/drivers/media/usb/pvrusb2/pvrusb2-ctrl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pvr2_ctrl_range_check
  2. pvr2_ctrl_set_value
  3. pvr2_ctrl_set_mask_value
  4. pvr2_ctrl_get_value
  5. pvr2_ctrl_get_type
  6. pvr2_ctrl_get_max
  7. pvr2_ctrl_get_min
  8. pvr2_ctrl_get_def
  9. pvr2_ctrl_get_cnt
  10. pvr2_ctrl_get_mask
  11. pvr2_ctrl_get_name
  12. pvr2_ctrl_get_desc
  13. pvr2_ctrl_get_valname
  14. pvr2_ctrl_get_v4lid
  15. pvr2_ctrl_get_v4lflags
  16. pvr2_ctrl_is_writable
  17. pvr2_ctrl_has_custom_symbols
  18. pvr2_ctrl_custom_value_to_sym
  19. pvr2_ctrl_custom_sym_to_value
  20. gen_bitmask_string
  21. parse_token
  22. parse_mtoken
  23. parse_tlist
  24. pvr2_ctrl_sym_to_value
  25. pvr2_ctrl_value_to_sym_internal
  26. pvr2_ctrl_value_to_sym

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
   5  */
   6 
   7 #include "pvrusb2-ctrl.h"
   8 #include "pvrusb2-hdw-internal.h"
   9 #include <linux/errno.h>
  10 #include <linux/string.h>
  11 #include <linux/mutex.h>
  12 
  13 
  14 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
  15 {
  16         if (cptr->info->check_value) {
  17                 if (!cptr->info->check_value(cptr,val)) return -ERANGE;
  18         } else if (cptr->info->type == pvr2_ctl_enum) {
  19                 if (val < 0) return -ERANGE;
  20                 if (val >= cptr->info->def.type_enum.count) return -ERANGE;
  21         } else {
  22                 int lim;
  23                 lim = cptr->info->def.type_int.min_value;
  24                 if (cptr->info->get_min_value) {
  25                         cptr->info->get_min_value(cptr,&lim);
  26                 }
  27                 if (val < lim) return -ERANGE;
  28                 lim = cptr->info->def.type_int.max_value;
  29                 if (cptr->info->get_max_value) {
  30                         cptr->info->get_max_value(cptr,&lim);
  31                 }
  32                 if (val > lim) return -ERANGE;
  33         }
  34         return 0;
  35 }
  36 
  37 
  38 /* Set the given control. */
  39 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
  40 {
  41         return pvr2_ctrl_set_mask_value(cptr,~0,val);
  42 }
  43 
  44 
  45 /* Set/clear specific bits of the given control. */
  46 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
  47 {
  48         int ret = 0;
  49         if (!cptr) return -EINVAL;
  50         LOCK_TAKE(cptr->hdw->big_lock); do {
  51                 if (cptr->info->set_value) {
  52                         if (cptr->info->type == pvr2_ctl_bitmask) {
  53                                 mask &= cptr->info->def.type_bitmask.valid_bits;
  54                         } else if ((cptr->info->type == pvr2_ctl_int)||
  55                                    (cptr->info->type == pvr2_ctl_enum)) {
  56                                 ret = pvr2_ctrl_range_check(cptr,val);
  57                                 if (ret < 0) break;
  58                         } else if (cptr->info->type != pvr2_ctl_bool) {
  59                                 break;
  60                         }
  61                         ret = cptr->info->set_value(cptr,mask,val);
  62                 } else {
  63                         ret = -EPERM;
  64                 }
  65         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
  66         return ret;
  67 }
  68 
  69 
  70 /* Get the current value of the given control. */
  71 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
  72 {
  73         int ret = 0;
  74         if (!cptr) return -EINVAL;
  75         LOCK_TAKE(cptr->hdw->big_lock); do {
  76                 ret = cptr->info->get_value(cptr,valptr);
  77         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
  78         return ret;
  79 }
  80 
  81 
  82 /* Retrieve control's type */
  83 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
  84 {
  85         if (!cptr) return pvr2_ctl_int;
  86         return cptr->info->type;
  87 }
  88 
  89 
  90 /* Retrieve control's maximum value (int type) */
  91 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
  92 {
  93         int ret = 0;
  94         if (!cptr) return 0;
  95         LOCK_TAKE(cptr->hdw->big_lock); do {
  96                 if (cptr->info->get_max_value) {
  97                         cptr->info->get_max_value(cptr,&ret);
  98                 } else if (cptr->info->type == pvr2_ctl_int) {
  99                         ret = cptr->info->def.type_int.max_value;
 100                 }
 101         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 102         return ret;
 103 }
 104 
 105 
 106 /* Retrieve control's minimum value (int type) */
 107 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
 108 {
 109         int ret = 0;
 110         if (!cptr) return 0;
 111         LOCK_TAKE(cptr->hdw->big_lock); do {
 112                 if (cptr->info->get_min_value) {
 113                         cptr->info->get_min_value(cptr,&ret);
 114                 } else if (cptr->info->type == pvr2_ctl_int) {
 115                         ret = cptr->info->def.type_int.min_value;
 116                 }
 117         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 118         return ret;
 119 }
 120 
 121 
 122 /* Retrieve control's default value (any type) */
 123 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
 124 {
 125         int ret = 0;
 126         if (!cptr) return -EINVAL;
 127         LOCK_TAKE(cptr->hdw->big_lock); do {
 128                 if (cptr->info->get_def_value) {
 129                         ret = cptr->info->get_def_value(cptr, valptr);
 130                 } else {
 131                         *valptr = cptr->info->default_value;
 132                 }
 133         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 134         return ret;
 135 }
 136 
 137 
 138 /* Retrieve control's enumeration count (enum only) */
 139 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
 140 {
 141         int ret = 0;
 142         if (!cptr) return 0;
 143         LOCK_TAKE(cptr->hdw->big_lock); do {
 144                 if (cptr->info->type == pvr2_ctl_enum) {
 145                         ret = cptr->info->def.type_enum.count;
 146                 }
 147         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 148         return ret;
 149 }
 150 
 151 
 152 /* Retrieve control's valid mask bits (bit mask only) */
 153 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
 154 {
 155         int ret = 0;
 156         if (!cptr) return 0;
 157         LOCK_TAKE(cptr->hdw->big_lock); do {
 158                 if (cptr->info->type == pvr2_ctl_bitmask) {
 159                         ret = cptr->info->def.type_bitmask.valid_bits;
 160                 }
 161         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 162         return ret;
 163 }
 164 
 165 
 166 /* Retrieve the control's name */
 167 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
 168 {
 169         if (!cptr) return NULL;
 170         return cptr->info->name;
 171 }
 172 
 173 
 174 /* Retrieve the control's desc */
 175 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
 176 {
 177         if (!cptr) return NULL;
 178         return cptr->info->desc;
 179 }
 180 
 181 
 182 /* Retrieve a control enumeration or bit mask value */
 183 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
 184                           char *bptr,unsigned int bmax,
 185                           unsigned int *blen)
 186 {
 187         int ret = -EINVAL;
 188         if (!cptr) return 0;
 189         *blen = 0;
 190         LOCK_TAKE(cptr->hdw->big_lock); do {
 191                 if (cptr->info->type == pvr2_ctl_enum) {
 192                         const char * const *names;
 193                         names = cptr->info->def.type_enum.value_names;
 194                         if (pvr2_ctrl_range_check(cptr,val) == 0) {
 195                                 if (names[val]) {
 196                                         *blen = scnprintf(
 197                                                 bptr,bmax,"%s",
 198                                                 names[val]);
 199                                 } else {
 200                                         *blen = 0;
 201                                 }
 202                                 ret = 0;
 203                         }
 204                 } else if (cptr->info->type == pvr2_ctl_bitmask) {
 205                         const char **names;
 206                         unsigned int idx;
 207                         int msk;
 208                         names = cptr->info->def.type_bitmask.bit_names;
 209                         val &= cptr->info->def.type_bitmask.valid_bits;
 210                         for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
 211                                 if (val & msk) {
 212                                         *blen = scnprintf(bptr,bmax,"%s",
 213                                                           names[idx]);
 214                                         ret = 0;
 215                                         break;
 216                                 }
 217                         }
 218                 }
 219         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 220         return ret;
 221 }
 222 
 223 
 224 /* Return V4L ID for this control or zero if none */
 225 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
 226 {
 227         if (!cptr) return 0;
 228         return cptr->info->v4l_id;
 229 }
 230 
 231 
 232 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
 233 {
 234         unsigned int flags = 0;
 235 
 236         if (cptr->info->get_v4lflags) {
 237                 flags = cptr->info->get_v4lflags(cptr);
 238         }
 239 
 240         if (cptr->info->set_value) {
 241                 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
 242         } else {
 243                 flags |= V4L2_CTRL_FLAG_READ_ONLY;
 244         }
 245 
 246         return flags;
 247 }
 248 
 249 
 250 /* Return true if control is writable */
 251 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
 252 {
 253         if (!cptr) return 0;
 254         return cptr->info->set_value != NULL;
 255 }
 256 
 257 
 258 /* Return true if control has custom symbolic representation */
 259 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
 260 {
 261         if (!cptr) return 0;
 262         if (!cptr->info->val_to_sym) return 0;
 263         if (!cptr->info->sym_to_val) return 0;
 264         return !0;
 265 }
 266 
 267 
 268 /* Convert a given mask/val to a custom symbolic value */
 269 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
 270                                   int mask,int val,
 271                                   char *buf,unsigned int maxlen,
 272                                   unsigned int *len)
 273 {
 274         if (!cptr) return -EINVAL;
 275         if (!cptr->info->val_to_sym) return -EINVAL;
 276         return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
 277 }
 278 
 279 
 280 /* Convert a symbolic value to a mask/value pair */
 281 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
 282                                   const char *buf,unsigned int len,
 283                                   int *maskptr,int *valptr)
 284 {
 285         if (!cptr) return -EINVAL;
 286         if (!cptr->info->sym_to_val) return -EINVAL;
 287         return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
 288 }
 289 
 290 
 291 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
 292                                        const char **names,
 293                                        char *ptr,unsigned int len)
 294 {
 295         unsigned int idx;
 296         long sm,um;
 297         int spcFl;
 298         unsigned int uc,cnt;
 299         const char *idStr;
 300 
 301         spcFl = 0;
 302         uc = 0;
 303         um = 0;
 304         for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
 305                 if (sm & msk) {
 306                         msk &= ~sm;
 307                         idStr = names[idx];
 308                         if (idStr) {
 309                                 cnt = scnprintf(ptr,len,"%s%s%s",
 310                                                 (spcFl ? " " : ""),
 311                                                 (msk_only ? "" :
 312                                                  ((val & sm) ? "+" : "-")),
 313                                                 idStr);
 314                                 ptr += cnt; len -= cnt; uc += cnt;
 315                                 spcFl = !0;
 316                         } else {
 317                                 um |= sm;
 318                         }
 319                 }
 320         }
 321         if (um) {
 322                 if (msk_only) {
 323                         cnt = scnprintf(ptr,len,"%s0x%lx",
 324                                         (spcFl ? " " : ""),
 325                                         um);
 326                         ptr += cnt; len -= cnt; uc += cnt;
 327                         spcFl = !0;
 328                 } else if (um & val) {
 329                         cnt = scnprintf(ptr,len,"%s+0x%lx",
 330                                         (spcFl ? " " : ""),
 331                                         um & val);
 332                         ptr += cnt; len -= cnt; uc += cnt;
 333                         spcFl = !0;
 334                 } else if (um & ~val) {
 335                         cnt = scnprintf(ptr,len,"%s+0x%lx",
 336                                         (spcFl ? " " : ""),
 337                                         um & ~val);
 338                         ptr += cnt; len -= cnt; uc += cnt;
 339                         spcFl = !0;
 340                 }
 341         }
 342         return uc;
 343 }
 344 
 345 
 346 static const char *boolNames[] = {
 347         "false",
 348         "true",
 349         "no",
 350         "yes",
 351 };
 352 
 353 
 354 static int parse_token(const char *ptr,unsigned int len,
 355                        int *valptr,
 356                        const char * const *names, unsigned int namecnt)
 357 {
 358         char buf[33];
 359         unsigned int slen;
 360         unsigned int idx;
 361         int negfl;
 362         char *p2;
 363         *valptr = 0;
 364         if (!names) namecnt = 0;
 365         for (idx = 0; idx < namecnt; idx++) {
 366                 if (!names[idx]) continue;
 367                 slen = strlen(names[idx]);
 368                 if (slen != len) continue;
 369                 if (memcmp(names[idx],ptr,slen)) continue;
 370                 *valptr = idx;
 371                 return 0;
 372         }
 373         negfl = 0;
 374         if ((*ptr == '-') || (*ptr == '+')) {
 375                 negfl = (*ptr == '-');
 376                 ptr++; len--;
 377         }
 378         if (len >= sizeof(buf)) return -EINVAL;
 379         memcpy(buf,ptr,len);
 380         buf[len] = 0;
 381         *valptr = simple_strtol(buf,&p2,0);
 382         if (negfl) *valptr = -(*valptr);
 383         if (*p2) return -EINVAL;
 384         return 1;
 385 }
 386 
 387 
 388 static int parse_mtoken(const char *ptr,unsigned int len,
 389                         int *valptr,
 390                         const char **names,int valid_bits)
 391 {
 392         char buf[33];
 393         unsigned int slen;
 394         unsigned int idx;
 395         char *p2;
 396         int msk;
 397         *valptr = 0;
 398         for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
 399                 if (!(msk & valid_bits)) continue;
 400                 valid_bits &= ~msk;
 401                 if (!names[idx]) continue;
 402                 slen = strlen(names[idx]);
 403                 if (slen != len) continue;
 404                 if (memcmp(names[idx],ptr,slen)) continue;
 405                 *valptr = msk;
 406                 return 0;
 407         }
 408         if (len >= sizeof(buf)) return -EINVAL;
 409         memcpy(buf,ptr,len);
 410         buf[len] = 0;
 411         *valptr = simple_strtol(buf,&p2,0);
 412         if (*p2) return -EINVAL;
 413         return 0;
 414 }
 415 
 416 
 417 static int parse_tlist(const char *ptr,unsigned int len,
 418                        int *maskptr,int *valptr,
 419                        const char **names,int valid_bits)
 420 {
 421         unsigned int cnt;
 422         int mask,val,kv,mode,ret;
 423         mask = 0;
 424         val = 0;
 425         ret = 0;
 426         while (len) {
 427                 cnt = 0;
 428                 while ((cnt < len) &&
 429                        ((ptr[cnt] <= 32) ||
 430                         (ptr[cnt] >= 127))) cnt++;
 431                 ptr += cnt;
 432                 len -= cnt;
 433                 mode = 0;
 434                 if ((*ptr == '-') || (*ptr == '+')) {
 435                         mode = (*ptr == '-') ? -1 : 1;
 436                         ptr++;
 437                         len--;
 438                 }
 439                 cnt = 0;
 440                 while (cnt < len) {
 441                         if (ptr[cnt] <= 32) break;
 442                         if (ptr[cnt] >= 127) break;
 443                         cnt++;
 444                 }
 445                 if (!cnt) break;
 446                 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
 447                         ret = -EINVAL;
 448                         break;
 449                 }
 450                 ptr += cnt;
 451                 len -= cnt;
 452                 switch (mode) {
 453                 case 0:
 454                         mask = valid_bits;
 455                         val |= kv;
 456                         break;
 457                 case -1:
 458                         mask |= kv;
 459                         val &= ~kv;
 460                         break;
 461                 case 1:
 462                         mask |= kv;
 463                         val |= kv;
 464                         break;
 465                 default:
 466                         break;
 467                 }
 468         }
 469         *maskptr = mask;
 470         *valptr = val;
 471         return ret;
 472 }
 473 
 474 
 475 /* Convert a symbolic value to a mask/value pair */
 476 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
 477                            const char *ptr,unsigned int len,
 478                            int *maskptr,int *valptr)
 479 {
 480         int ret = -EINVAL;
 481         unsigned int cnt;
 482 
 483         *maskptr = 0;
 484         *valptr = 0;
 485 
 486         cnt = 0;
 487         while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
 488         len -= cnt; ptr += cnt;
 489         cnt = 0;
 490         while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
 491                                (ptr[len-(cnt+1)] >= 127))) cnt++;
 492         len -= cnt;
 493 
 494         if (!len) return -EINVAL;
 495 
 496         LOCK_TAKE(cptr->hdw->big_lock); do {
 497                 if (cptr->info->type == pvr2_ctl_int) {
 498                         ret = parse_token(ptr,len,valptr,NULL,0);
 499                         if (ret >= 0) {
 500                                 ret = pvr2_ctrl_range_check(cptr,*valptr);
 501                         }
 502                         *maskptr = ~0;
 503                 } else if (cptr->info->type == pvr2_ctl_bool) {
 504                         ret = parse_token(ptr,len,valptr,boolNames,
 505                                           ARRAY_SIZE(boolNames));
 506                         if (ret == 1) {
 507                                 *valptr = *valptr ? !0 : 0;
 508                         } else if (ret == 0) {
 509                                 *valptr = (*valptr & 1) ? !0 : 0;
 510                         }
 511                         *maskptr = 1;
 512                 } else if (cptr->info->type == pvr2_ctl_enum) {
 513                         ret = parse_token(
 514                                 ptr,len,valptr,
 515                                 cptr->info->def.type_enum.value_names,
 516                                 cptr->info->def.type_enum.count);
 517                         if (ret >= 0) {
 518                                 ret = pvr2_ctrl_range_check(cptr,*valptr);
 519                         }
 520                         *maskptr = ~0;
 521                 } else if (cptr->info->type == pvr2_ctl_bitmask) {
 522                         ret = parse_tlist(
 523                                 ptr,len,maskptr,valptr,
 524                                 cptr->info->def.type_bitmask.bit_names,
 525                                 cptr->info->def.type_bitmask.valid_bits);
 526                 }
 527         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 528         return ret;
 529 }
 530 
 531 
 532 /* Convert a given mask/val to a symbolic value */
 533 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
 534                                     int mask,int val,
 535                                     char *buf,unsigned int maxlen,
 536                                     unsigned int *len)
 537 {
 538         int ret = -EINVAL;
 539 
 540         *len = 0;
 541         if (cptr->info->type == pvr2_ctl_int) {
 542                 *len = scnprintf(buf,maxlen,"%d",val);
 543                 ret = 0;
 544         } else if (cptr->info->type == pvr2_ctl_bool) {
 545                 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
 546                 ret = 0;
 547         } else if (cptr->info->type == pvr2_ctl_enum) {
 548                 const char * const *names;
 549                 names = cptr->info->def.type_enum.value_names;
 550                 if ((val >= 0) &&
 551                     (val < cptr->info->def.type_enum.count)) {
 552                         if (names[val]) {
 553                                 *len = scnprintf(
 554                                         buf,maxlen,"%s",
 555                                         names[val]);
 556                         } else {
 557                                 *len = 0;
 558                         }
 559                         ret = 0;
 560                 }
 561         } else if (cptr->info->type == pvr2_ctl_bitmask) {
 562                 *len = gen_bitmask_string(
 563                         val & mask & cptr->info->def.type_bitmask.valid_bits,
 564                         ~0,!0,
 565                         cptr->info->def.type_bitmask.bit_names,
 566                         buf,maxlen);
 567         }
 568         return ret;
 569 }
 570 
 571 
 572 /* Convert a given mask/val to a symbolic value */
 573 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
 574                            int mask,int val,
 575                            char *buf,unsigned int maxlen,
 576                            unsigned int *len)
 577 {
 578         int ret;
 579         LOCK_TAKE(cptr->hdw->big_lock); do {
 580                 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
 581                                                       buf,maxlen,len);
 582         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
 583         return ret;
 584 }

/* [<][>][^][v][top][bottom][index][help] */