1/* 2 * 3 * $Id: pvrusb2-ctrl.c,v 1.1.1.1 2007/08/03 18:52:41 Exp $ 4 * 5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 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 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22#include "pvrusb2-ctrl.h" 23#include "pvrusb2-hdw-internal.h" 24#include <linux/errno.h> 25#include <linux/string.h> 26#include <linux/mutex.h> 27 28 29static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val) 30{ 31 if (cptr->info->check_value) { 32 if (!cptr->info->check_value(cptr,val)) return -ERANGE; 33 } else { 34 int lim; 35 lim = cptr->info->def.type_int.min_value; 36 if (cptr->info->get_min_value) { 37 cptr->info->get_min_value(cptr,&lim); 38 } 39 if (val < lim) return -ERANGE; 40 lim = cptr->info->def.type_int.max_value; 41 if (cptr->info->get_max_value) { 42 cptr->info->get_max_value(cptr,&lim); 43 } 44 if (val > lim) return -ERANGE; 45 } 46 return 0; 47} 48 49 50/* Set the given control. */ 51int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val) 52{ 53 return pvr2_ctrl_set_mask_value(cptr,~0,val); 54} 55 56 57/* Set/clear specific bits of the given control. */ 58int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val) 59{ 60 int ret = 0; 61 if (!cptr) return -EINVAL; 62 LOCK_TAKE(cptr->hdw->big_lock); do { 63 if (cptr->info->set_value != 0) { 64 if (cptr->info->type == pvr2_ctl_bitmask) { 65 mask &= cptr->info->def.type_bitmask.valid_bits; 66 } else if (cptr->info->type == pvr2_ctl_int) { 67 ret = pvr2_ctrl_range_check(cptr,val); 68 if (ret < 0) break; 69 } else if (cptr->info->type == pvr2_ctl_enum) { 70 if (val >= cptr->info->def.type_enum.count) { 71 break; 72 } 73 } else if (cptr->info->type != pvr2_ctl_bool) { 74 break; 75 } 76 ret = cptr->info->set_value(cptr,mask,val); 77 } else { 78 ret = -EPERM; 79 } 80 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 81 return ret; 82} 83 84 85/* Get the current value of the given control. */ 86int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr) 87{ 88 int ret = 0; 89 if (!cptr) return -EINVAL; 90 LOCK_TAKE(cptr->hdw->big_lock); do { 91 ret = cptr->info->get_value(cptr,valptr); 92 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 93 return ret; 94} 95 96 97/* Retrieve control's type */ 98enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr) 99{ 100 if (!cptr) return pvr2_ctl_int; 101 return cptr->info->type; 102} 103 104 105/* Retrieve control's maximum value (int type) */ 106int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr) 107{ 108 int ret = 0; 109 if (!cptr) return 0; 110 LOCK_TAKE(cptr->hdw->big_lock); do { 111 if (cptr->info->get_max_value) { 112 cptr->info->get_max_value(cptr,&ret); 113 } else if (cptr->info->type == pvr2_ctl_int) { 114 ret = cptr->info->def.type_int.max_value; 115 } 116 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 117 return ret; 118} 119 120 121/* Retrieve control's minimum value (int type) */ 122int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) 123{ 124 int ret = 0; 125 if (!cptr) return 0; 126 LOCK_TAKE(cptr->hdw->big_lock); do { 127 if (cptr->info->get_min_value) { 128 cptr->info->get_min_value(cptr,&ret); 129 } else if (cptr->info->type == pvr2_ctl_int) { 130 ret = cptr->info->def.type_int.min_value; 131 } 132 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 133 return ret; 134} 135 136 137/* Retrieve control's default value (any type) */ 138int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr) 139{ 140 int ret = 0; 141 if (!cptr) return 0; 142 LOCK_TAKE(cptr->hdw->big_lock); do { 143 if (cptr->info->type == pvr2_ctl_int) { 144 ret = cptr->info->default_value; 145 } 146 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 147 return ret; 148} 149 150 151/* Retrieve control's enumeration count (enum only) */ 152int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr) 153{ 154 int ret = 0; 155 if (!cptr) return 0; 156 LOCK_TAKE(cptr->hdw->big_lock); do { 157 if (cptr->info->type == pvr2_ctl_enum) { 158 ret = cptr->info->def.type_enum.count; 159 } 160 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 161 return ret; 162} 163 164 165/* Retrieve control's valid mask bits (bit mask only) */ 166int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr) 167{ 168 int ret = 0; 169 if (!cptr) return 0; 170 LOCK_TAKE(cptr->hdw->big_lock); do { 171 if (cptr->info->type == pvr2_ctl_bitmask) { 172 ret = cptr->info->def.type_bitmask.valid_bits; 173 } 174 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 175 return ret; 176} 177 178 179/* Retrieve the control's name */ 180const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr) 181{ 182 if (!cptr) return NULL; 183 return cptr->info->name; 184} 185 186 187/* Retrieve the control's desc */ 188const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr) 189{ 190 if (!cptr) return NULL; 191 return cptr->info->desc; 192} 193 194 195/* Retrieve a control enumeration or bit mask value */ 196int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, 197 char *bptr,unsigned int bmax, 198 unsigned int *blen) 199{ 200 int ret = -EINVAL; 201 if (!cptr) return 0; 202 *blen = 0; 203 LOCK_TAKE(cptr->hdw->big_lock); do { 204 if (cptr->info->type == pvr2_ctl_enum) { 205 const char **names; 206 names = cptr->info->def.type_enum.value_names; 207 if ((val >= 0) && 208 (val < cptr->info->def.type_enum.count)) { 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 != 0; 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 **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 if (maskptr) *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 if (maskptr) *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 ((*valptr < 0) || 533 (*valptr >= cptr->info->def.type_enum.count))) { 534 ret = -ERANGE; 535 } 536 if (maskptr) *maskptr = ~0; 537 } else if (cptr->info->type == pvr2_ctl_bitmask) { 538 ret = parse_tlist( 539 ptr,len,maskptr,valptr, 540 cptr->info->def.type_bitmask.bit_names, 541 cptr->info->def.type_bitmask.valid_bits); 542 } 543 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 544 return ret; 545} 546 547 548/* Convert a given mask/val to a symbolic value */ 549int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr, 550 int mask,int val, 551 char *buf,unsigned int maxlen, 552 unsigned int *len) 553{ 554 int ret = -EINVAL; 555 556 *len = 0; 557 if (cptr->info->type == pvr2_ctl_int) { 558 *len = scnprintf(buf,maxlen,"%d",val); 559 ret = 0; 560 } else if (cptr->info->type == pvr2_ctl_bool) { 561 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false"); 562 ret = 0; 563 } else if (cptr->info->type == pvr2_ctl_enum) { 564 const char **names; 565 names = cptr->info->def.type_enum.value_names; 566 if ((val >= 0) && 567 (val < cptr->info->def.type_enum.count)) { 568 if (names[val]) { 569 *len = scnprintf( 570 buf,maxlen,"%s", 571 names[val]); 572 } else { 573 *len = 0; 574 } 575 ret = 0; 576 } 577 } else if (cptr->info->type == pvr2_ctl_bitmask) { 578 *len = gen_bitmask_string( 579 val & mask & cptr->info->def.type_bitmask.valid_bits, 580 ~0,!0, 581 cptr->info->def.type_bitmask.bit_names, 582 buf,maxlen); 583 } 584 return ret; 585} 586 587 588/* Convert a given mask/val to a symbolic value */ 589int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr, 590 int mask,int val, 591 char *buf,unsigned int maxlen, 592 unsigned int *len) 593{ 594 int ret; 595 LOCK_TAKE(cptr->hdw->big_lock); do { 596 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val, 597 buf,maxlen,len); 598 } while(0); LOCK_GIVE(cptr->hdw->big_lock); 599 return ret; 600} 601 602 603/* 604 Stuff for Emacs to see, in order to encourage consistent editing style: 605 *** Local Variables: *** 606 *** mode: c *** 607 *** fill-column: 75 *** 608 *** tab-width: 8 *** 609 *** c-basic-offset: 8 *** 610 *** End: *** 611 */ 612