1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
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
);