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