1 // SPDX-License-Identifier: GPL-2.0-only
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>
14 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
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;
23 lim = cptr->info->def.type_int.min_value;
24 if (cptr->info->get_min_value) {
25 cptr->info->get_min_value(cptr,&lim);
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);
32 if (val > lim) return -ERANGE;
38 /* Set the given control. */
39 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
41 return pvr2_ctrl_set_mask_value(cptr,~0,val);
45 /* Set/clear specific bits of the given control. */
46 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
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);
58 } else if (cptr->info->type != pvr2_ctl_bool) {
61 ret = cptr->info->set_value(cptr,mask,val);
65 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
70 /* Get the current value of the given control. */
71 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
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);
82 /* Retrieve control's type */
83 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
85 if (!cptr) return pvr2_ctl_int;
86 return cptr->info->type;
90 /* Retrieve control's maximum value (int type) */
91 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
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;
101 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
106 /* Retrieve control's minimum value (int type) */
107 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
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;
117 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
122 /* Retrieve control's default value (any type) */
123 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
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);
131 *valptr = cptr->info->default_value;
133 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
138 /* Retrieve control's enumeration count (enum only) */
139 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
143 LOCK_TAKE(cptr->hdw->big_lock); do {
144 if (cptr->info->type == pvr2_ctl_enum) {
145 ret = cptr->info->def.type_enum.count;
147 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
152 /* Retrieve control's valid mask bits (bit mask only) */
153 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
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;
161 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
166 /* Retrieve the control's name */
167 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
169 if (!cptr) return NULL;
170 return cptr->info->name;
174 /* Retrieve the control's desc */
175 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
177 if (!cptr) return NULL;
178 return cptr->info->desc;
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,
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) {
204 } else if (cptr->info->type == pvr2_ctl_bitmask) {
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) {
212 *blen = scnprintf(bptr,bmax,"%s",
219 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
224 /* Return V4L ID for this control or zero if none */
225 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
228 return cptr->info->v4l_id;
232 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
234 unsigned int flags = 0;
236 if (cptr->info->get_v4lflags) {
237 flags = cptr->info->get_v4lflags(cptr);
240 if (cptr->info->set_value) {
241 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
243 flags |= V4L2_CTRL_FLAG_READ_ONLY;
250 /* Return true if control is writable */
251 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
254 return cptr->info->set_value != NULL;
258 /* Return true if control has custom symbolic representation */
259 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
262 if (!cptr->info->val_to_sym) return 0;
263 if (!cptr->info->sym_to_val) return 0;
268 /* Convert a given mask/val to a custom symbolic value */
269 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
271 char *buf,unsigned int maxlen,
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);
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)
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);
291 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
293 char *ptr,unsigned int len)
304 for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
309 cnt = scnprintf(ptr,len,"%s%s%s",
312 ((val & sm) ? "+" : "-")),
314 ptr += cnt; len -= cnt; uc += cnt;
323 cnt = scnprintf(ptr,len,"%s0x%lx",
326 ptr += cnt; len -= cnt; uc += cnt;
328 } else if (um & val) {
329 cnt = scnprintf(ptr,len,"%s+0x%lx",
332 ptr += cnt; len -= cnt; uc += cnt;
334 } else if (um & ~val) {
335 cnt = scnprintf(ptr,len,"%s+0x%lx",
338 ptr += cnt; len -= cnt; uc += cnt;
346 static const char *boolNames[] = {
354 static int parse_token(const char *ptr,unsigned int len,
356 const char * const *names, unsigned int namecnt)
361 if (!names) namecnt = 0;
362 for (idx = 0; idx < namecnt; idx++) {
363 if (!names[idx]) continue;
364 slen = strlen(names[idx]);
365 if (slen != len) continue;
366 if (memcmp(names[idx],ptr,slen)) continue;
370 return kstrtoint(ptr, 0, valptr) ? -EINVAL : 1;
374 static int parse_mtoken(const char *ptr,unsigned int len,
376 const char **names,int valid_bits)
382 for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
383 if (!(msk & valid_bits)) continue;
385 if (!names[idx]) continue;
386 slen = strlen(names[idx]);
387 if (slen != len) continue;
388 if (memcmp(names[idx],ptr,slen)) continue;
392 return kstrtoint(ptr, 0, valptr);
396 static int parse_tlist(const char *ptr,unsigned int len,
397 int *maskptr,int *valptr,
398 const char **names,int valid_bits)
401 int mask,val,kv,mode,ret;
407 while ((cnt < len) &&
409 (ptr[cnt] >= 127))) cnt++;
413 if ((*ptr == '-') || (*ptr == '+')) {
414 mode = (*ptr == '-') ? -1 : 1;
420 if (ptr[cnt] <= 32) break;
421 if (ptr[cnt] >= 127) break;
425 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
454 /* Convert a symbolic value to a mask/value pair */
455 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
456 const char *ptr,unsigned int len,
457 int *maskptr,int *valptr)
466 while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
467 len -= cnt; ptr += cnt;
469 while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
470 (ptr[len-(cnt+1)] >= 127))) cnt++;
473 if (!len) return -EINVAL;
475 LOCK_TAKE(cptr->hdw->big_lock); do {
476 if (cptr->info->type == pvr2_ctl_int) {
477 ret = parse_token(ptr,len,valptr,NULL,0);
479 ret = pvr2_ctrl_range_check(cptr,*valptr);
482 } else if (cptr->info->type == pvr2_ctl_bool) {
483 ret = parse_token(ptr,len,valptr,boolNames,
484 ARRAY_SIZE(boolNames));
486 *valptr = *valptr ? !0 : 0;
487 } else if (ret == 0) {
488 *valptr = (*valptr & 1) ? !0 : 0;
491 } else if (cptr->info->type == pvr2_ctl_enum) {
494 cptr->info->def.type_enum.value_names,
495 cptr->info->def.type_enum.count);
497 ret = pvr2_ctrl_range_check(cptr,*valptr);
500 } else if (cptr->info->type == pvr2_ctl_bitmask) {
502 ptr,len,maskptr,valptr,
503 cptr->info->def.type_bitmask.bit_names,
504 cptr->info->def.type_bitmask.valid_bits);
506 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
511 /* Convert a given mask/val to a symbolic value */
512 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
514 char *buf,unsigned int maxlen,
520 if (cptr->info->type == pvr2_ctl_int) {
521 *len = scnprintf(buf,maxlen,"%d",val);
523 } else if (cptr->info->type == pvr2_ctl_bool) {
524 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
526 } else if (cptr->info->type == pvr2_ctl_enum) {
527 const char * const *names;
528 names = cptr->info->def.type_enum.value_names;
530 (val < cptr->info->def.type_enum.count)) {
540 } else if (cptr->info->type == pvr2_ctl_bitmask) {
541 *len = gen_bitmask_string(
542 val & mask & cptr->info->def.type_bitmask.valid_bits,
544 cptr->info->def.type_bitmask.bit_names,
551 /* Convert a given mask/val to a symbolic value */
552 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
554 char *buf,unsigned int maxlen,
558 LOCK_TAKE(cptr->hdw->big_lock); do {
559 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
561 } while(0); LOCK_GIVE(cptr->hdw->big_lock);