0001
0002
0003
0004
0005
0006
0007 #include "pvrusb2-ctrl.h"
0008 #include "pvrusb2-hdw-internal.h"
0009 #include <linux/errno.h>
0010 #include <linux/string.h>
0011 #include <linux/mutex.h>
0012
0013
0014 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
0015 {
0016 if (cptr->info->check_value) {
0017 if (!cptr->info->check_value(cptr,val)) return -ERANGE;
0018 } else if (cptr->info->type == pvr2_ctl_enum) {
0019 if (val < 0) return -ERANGE;
0020 if (val >= cptr->info->def.type_enum.count) return -ERANGE;
0021 } else {
0022 int lim;
0023 lim = cptr->info->def.type_int.min_value;
0024 if (cptr->info->get_min_value) {
0025 cptr->info->get_min_value(cptr,&lim);
0026 }
0027 if (val < lim) return -ERANGE;
0028 lim = cptr->info->def.type_int.max_value;
0029 if (cptr->info->get_max_value) {
0030 cptr->info->get_max_value(cptr,&lim);
0031 }
0032 if (val > lim) return -ERANGE;
0033 }
0034 return 0;
0035 }
0036
0037
0038
0039 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
0040 {
0041 return pvr2_ctrl_set_mask_value(cptr,~0,val);
0042 }
0043
0044
0045
0046 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
0047 {
0048 int ret = 0;
0049 if (!cptr) return -EINVAL;
0050 LOCK_TAKE(cptr->hdw->big_lock); do {
0051 if (cptr->info->set_value) {
0052 if (cptr->info->type == pvr2_ctl_bitmask) {
0053 mask &= cptr->info->def.type_bitmask.valid_bits;
0054 } else if ((cptr->info->type == pvr2_ctl_int)||
0055 (cptr->info->type == pvr2_ctl_enum)) {
0056 ret = pvr2_ctrl_range_check(cptr,val);
0057 if (ret < 0) break;
0058 } else if (cptr->info->type != pvr2_ctl_bool) {
0059 break;
0060 }
0061 ret = cptr->info->set_value(cptr,mask,val);
0062 } else {
0063 ret = -EPERM;
0064 }
0065 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0066 return ret;
0067 }
0068
0069
0070
0071 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
0072 {
0073 int ret = 0;
0074 if (!cptr) return -EINVAL;
0075 LOCK_TAKE(cptr->hdw->big_lock); do {
0076 ret = cptr->info->get_value(cptr,valptr);
0077 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0078 return ret;
0079 }
0080
0081
0082
0083 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
0084 {
0085 if (!cptr) return pvr2_ctl_int;
0086 return cptr->info->type;
0087 }
0088
0089
0090
0091 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
0092 {
0093 int ret = 0;
0094 if (!cptr) return 0;
0095 LOCK_TAKE(cptr->hdw->big_lock); do {
0096 if (cptr->info->get_max_value) {
0097 cptr->info->get_max_value(cptr,&ret);
0098 } else if (cptr->info->type == pvr2_ctl_int) {
0099 ret = cptr->info->def.type_int.max_value;
0100 }
0101 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0102 return ret;
0103 }
0104
0105
0106
0107 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
0108 {
0109 int ret = 0;
0110 if (!cptr) return 0;
0111 LOCK_TAKE(cptr->hdw->big_lock); do {
0112 if (cptr->info->get_min_value) {
0113 cptr->info->get_min_value(cptr,&ret);
0114 } else if (cptr->info->type == pvr2_ctl_int) {
0115 ret = cptr->info->def.type_int.min_value;
0116 }
0117 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0118 return ret;
0119 }
0120
0121
0122
0123 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
0124 {
0125 int ret = 0;
0126 if (!cptr) return -EINVAL;
0127 LOCK_TAKE(cptr->hdw->big_lock); do {
0128 if (cptr->info->get_def_value) {
0129 ret = cptr->info->get_def_value(cptr, valptr);
0130 } else {
0131 *valptr = cptr->info->default_value;
0132 }
0133 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0134 return ret;
0135 }
0136
0137
0138
0139 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
0140 {
0141 int ret = 0;
0142 if (!cptr) return 0;
0143 LOCK_TAKE(cptr->hdw->big_lock); do {
0144 if (cptr->info->type == pvr2_ctl_enum) {
0145 ret = cptr->info->def.type_enum.count;
0146 }
0147 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0148 return ret;
0149 }
0150
0151
0152
0153 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
0154 {
0155 int ret = 0;
0156 if (!cptr) return 0;
0157 LOCK_TAKE(cptr->hdw->big_lock); do {
0158 if (cptr->info->type == pvr2_ctl_bitmask) {
0159 ret = cptr->info->def.type_bitmask.valid_bits;
0160 }
0161 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0162 return ret;
0163 }
0164
0165
0166
0167 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
0168 {
0169 if (!cptr) return NULL;
0170 return cptr->info->name;
0171 }
0172
0173
0174
0175 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
0176 {
0177 if (!cptr) return NULL;
0178 return cptr->info->desc;
0179 }
0180
0181
0182
0183 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
0184 char *bptr,unsigned int bmax,
0185 unsigned int *blen)
0186 {
0187 int ret = -EINVAL;
0188 if (!cptr) return 0;
0189 *blen = 0;
0190 LOCK_TAKE(cptr->hdw->big_lock); do {
0191 if (cptr->info->type == pvr2_ctl_enum) {
0192 const char * const *names;
0193 names = cptr->info->def.type_enum.value_names;
0194 if (pvr2_ctrl_range_check(cptr,val) == 0) {
0195 if (names[val]) {
0196 *blen = scnprintf(
0197 bptr,bmax,"%s",
0198 names[val]);
0199 } else {
0200 *blen = 0;
0201 }
0202 ret = 0;
0203 }
0204 } else if (cptr->info->type == pvr2_ctl_bitmask) {
0205 const char **names;
0206 unsigned int idx;
0207 int msk;
0208 names = cptr->info->def.type_bitmask.bit_names;
0209 val &= cptr->info->def.type_bitmask.valid_bits;
0210 for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
0211 if (val & msk) {
0212 *blen = scnprintf(bptr,bmax,"%s",
0213 names[idx]);
0214 ret = 0;
0215 break;
0216 }
0217 }
0218 }
0219 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0220 return ret;
0221 }
0222
0223
0224
0225 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
0226 {
0227 if (!cptr) return 0;
0228 return cptr->info->v4l_id;
0229 }
0230
0231
0232 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
0233 {
0234 unsigned int flags = 0;
0235
0236 if (cptr->info->get_v4lflags) {
0237 flags = cptr->info->get_v4lflags(cptr);
0238 }
0239
0240 if (cptr->info->set_value) {
0241 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
0242 } else {
0243 flags |= V4L2_CTRL_FLAG_READ_ONLY;
0244 }
0245
0246 return flags;
0247 }
0248
0249
0250
0251 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
0252 {
0253 if (!cptr) return 0;
0254 return cptr->info->set_value != NULL;
0255 }
0256
0257
0258
0259 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
0260 {
0261 if (!cptr) return 0;
0262 if (!cptr->info->val_to_sym) return 0;
0263 if (!cptr->info->sym_to_val) return 0;
0264 return !0;
0265 }
0266
0267
0268
0269 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
0270 int mask,int val,
0271 char *buf,unsigned int maxlen,
0272 unsigned int *len)
0273 {
0274 if (!cptr) return -EINVAL;
0275 if (!cptr->info->val_to_sym) return -EINVAL;
0276 return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
0277 }
0278
0279
0280
0281 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
0282 const char *buf,unsigned int len,
0283 int *maskptr,int *valptr)
0284 {
0285 if (!cptr) return -EINVAL;
0286 if (!cptr->info->sym_to_val) return -EINVAL;
0287 return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
0288 }
0289
0290
0291 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
0292 const char **names,
0293 char *ptr,unsigned int len)
0294 {
0295 unsigned int idx;
0296 long sm,um;
0297 int spcFl;
0298 unsigned int uc,cnt;
0299 const char *idStr;
0300
0301 spcFl = 0;
0302 uc = 0;
0303 um = 0;
0304 for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
0305 if (sm & msk) {
0306 msk &= ~sm;
0307 idStr = names[idx];
0308 if (idStr) {
0309 cnt = scnprintf(ptr,len,"%s%s%s",
0310 (spcFl ? " " : ""),
0311 (msk_only ? "" :
0312 ((val & sm) ? "+" : "-")),
0313 idStr);
0314 ptr += cnt; len -= cnt; uc += cnt;
0315 spcFl = !0;
0316 } else {
0317 um |= sm;
0318 }
0319 }
0320 }
0321 if (um) {
0322 if (msk_only) {
0323 cnt = scnprintf(ptr,len,"%s0x%lx",
0324 (spcFl ? " " : ""),
0325 um);
0326 ptr += cnt; len -= cnt; uc += cnt;
0327 spcFl = !0;
0328 } else if (um & val) {
0329 cnt = scnprintf(ptr,len,"%s+0x%lx",
0330 (spcFl ? " " : ""),
0331 um & val);
0332 ptr += cnt; len -= cnt; uc += cnt;
0333 spcFl = !0;
0334 } else if (um & ~val) {
0335 cnt = scnprintf(ptr,len,"%s+0x%lx",
0336 (spcFl ? " " : ""),
0337 um & ~val);
0338 ptr += cnt; len -= cnt; uc += cnt;
0339 spcFl = !0;
0340 }
0341 }
0342 return uc;
0343 }
0344
0345
0346 static const char *boolNames[] = {
0347 "false",
0348 "true",
0349 "no",
0350 "yes",
0351 };
0352
0353
0354 static int parse_token(const char *ptr,unsigned int len,
0355 int *valptr,
0356 const char * const *names, unsigned int namecnt)
0357 {
0358 unsigned int slen;
0359 unsigned int idx;
0360 *valptr = 0;
0361 if (!names) namecnt = 0;
0362 for (idx = 0; idx < namecnt; idx++) {
0363 if (!names[idx]) continue;
0364 slen = strlen(names[idx]);
0365 if (slen != len) continue;
0366 if (memcmp(names[idx],ptr,slen)) continue;
0367 *valptr = idx;
0368 return 0;
0369 }
0370 return kstrtoint(ptr, 0, valptr) ? -EINVAL : 1;
0371 }
0372
0373
0374 static int parse_mtoken(const char *ptr,unsigned int len,
0375 int *valptr,
0376 const char **names,int valid_bits)
0377 {
0378 unsigned int slen;
0379 unsigned int idx;
0380 int msk;
0381 *valptr = 0;
0382 for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
0383 if (!(msk & valid_bits)) continue;
0384 valid_bits &= ~msk;
0385 if (!names[idx]) continue;
0386 slen = strlen(names[idx]);
0387 if (slen != len) continue;
0388 if (memcmp(names[idx],ptr,slen)) continue;
0389 *valptr = msk;
0390 return 0;
0391 }
0392 return kstrtoint(ptr, 0, valptr);
0393 }
0394
0395
0396 static int parse_tlist(const char *ptr,unsigned int len,
0397 int *maskptr,int *valptr,
0398 const char **names,int valid_bits)
0399 {
0400 unsigned int cnt;
0401 int mask,val,kv,mode,ret;
0402 mask = 0;
0403 val = 0;
0404 ret = 0;
0405 while (len) {
0406 cnt = 0;
0407 while ((cnt < len) &&
0408 ((ptr[cnt] <= 32) ||
0409 (ptr[cnt] >= 127))) cnt++;
0410 ptr += cnt;
0411 len -= cnt;
0412 mode = 0;
0413 if ((*ptr == '-') || (*ptr == '+')) {
0414 mode = (*ptr == '-') ? -1 : 1;
0415 ptr++;
0416 len--;
0417 }
0418 cnt = 0;
0419 while (cnt < len) {
0420 if (ptr[cnt] <= 32) break;
0421 if (ptr[cnt] >= 127) break;
0422 cnt++;
0423 }
0424 if (!cnt) break;
0425 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
0426 ret = -EINVAL;
0427 break;
0428 }
0429 ptr += cnt;
0430 len -= cnt;
0431 switch (mode) {
0432 case 0:
0433 mask = valid_bits;
0434 val |= kv;
0435 break;
0436 case -1:
0437 mask |= kv;
0438 val &= ~kv;
0439 break;
0440 case 1:
0441 mask |= kv;
0442 val |= kv;
0443 break;
0444 default:
0445 break;
0446 }
0447 }
0448 *maskptr = mask;
0449 *valptr = val;
0450 return ret;
0451 }
0452
0453
0454
0455 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
0456 const char *ptr,unsigned int len,
0457 int *maskptr,int *valptr)
0458 {
0459 int ret = -EINVAL;
0460 unsigned int cnt;
0461
0462 *maskptr = 0;
0463 *valptr = 0;
0464
0465 cnt = 0;
0466 while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
0467 len -= cnt; ptr += cnt;
0468 cnt = 0;
0469 while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
0470 (ptr[len-(cnt+1)] >= 127))) cnt++;
0471 len -= cnt;
0472
0473 if (!len) return -EINVAL;
0474
0475 LOCK_TAKE(cptr->hdw->big_lock); do {
0476 if (cptr->info->type == pvr2_ctl_int) {
0477 ret = parse_token(ptr,len,valptr,NULL,0);
0478 if (ret >= 0) {
0479 ret = pvr2_ctrl_range_check(cptr,*valptr);
0480 }
0481 *maskptr = ~0;
0482 } else if (cptr->info->type == pvr2_ctl_bool) {
0483 ret = parse_token(ptr,len,valptr,boolNames,
0484 ARRAY_SIZE(boolNames));
0485 if (ret == 1) {
0486 *valptr = *valptr ? !0 : 0;
0487 } else if (ret == 0) {
0488 *valptr = (*valptr & 1) ? !0 : 0;
0489 }
0490 *maskptr = 1;
0491 } else if (cptr->info->type == pvr2_ctl_enum) {
0492 ret = parse_token(
0493 ptr,len,valptr,
0494 cptr->info->def.type_enum.value_names,
0495 cptr->info->def.type_enum.count);
0496 if (ret >= 0) {
0497 ret = pvr2_ctrl_range_check(cptr,*valptr);
0498 }
0499 *maskptr = ~0;
0500 } else if (cptr->info->type == pvr2_ctl_bitmask) {
0501 ret = parse_tlist(
0502 ptr,len,maskptr,valptr,
0503 cptr->info->def.type_bitmask.bit_names,
0504 cptr->info->def.type_bitmask.valid_bits);
0505 }
0506 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0507 return ret;
0508 }
0509
0510
0511
0512 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
0513 int mask,int val,
0514 char *buf,unsigned int maxlen,
0515 unsigned int *len)
0516 {
0517 int ret = -EINVAL;
0518
0519 *len = 0;
0520 if (cptr->info->type == pvr2_ctl_int) {
0521 *len = scnprintf(buf,maxlen,"%d",val);
0522 ret = 0;
0523 } else if (cptr->info->type == pvr2_ctl_bool) {
0524 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
0525 ret = 0;
0526 } else if (cptr->info->type == pvr2_ctl_enum) {
0527 const char * const *names;
0528 names = cptr->info->def.type_enum.value_names;
0529 if ((val >= 0) &&
0530 (val < cptr->info->def.type_enum.count)) {
0531 if (names[val]) {
0532 *len = scnprintf(
0533 buf,maxlen,"%s",
0534 names[val]);
0535 } else {
0536 *len = 0;
0537 }
0538 ret = 0;
0539 }
0540 } else if (cptr->info->type == pvr2_ctl_bitmask) {
0541 *len = gen_bitmask_string(
0542 val & mask & cptr->info->def.type_bitmask.valid_bits,
0543 ~0,!0,
0544 cptr->info->def.type_bitmask.bit_names,
0545 buf,maxlen);
0546 }
0547 return ret;
0548 }
0549
0550
0551
0552 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
0553 int mask,int val,
0554 char *buf,unsigned int maxlen,
0555 unsigned int *len)
0556 {
0557 int ret;
0558 LOCK_TAKE(cptr->hdw->big_lock); do {
0559 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
0560 buf,maxlen,len);
0561 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0562 return ret;
0563 }