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