4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
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
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.
17 #include "pvrusb2-ctrl.h"
18 #include "pvrusb2-hdw-internal.h"
19 #include <linux/errno.h>
20 #include <linux/string.h>
21 #include <linux/mutex.h>
24 static int pvr2_ctrl_range_check(struct pvr2_ctrl
*cptr
,int val
)
26 if (cptr
->info
->check_value
) {
27 if (!cptr
->info
->check_value(cptr
,val
)) return -ERANGE
;
28 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
29 if (val
< 0) return -ERANGE
;
30 if (val
>= cptr
->info
->def
.type_enum
.count
) return -ERANGE
;
33 lim
= cptr
->info
->def
.type_int
.min_value
;
34 if (cptr
->info
->get_min_value
) {
35 cptr
->info
->get_min_value(cptr
,&lim
);
37 if (val
< lim
) return -ERANGE
;
38 lim
= cptr
->info
->def
.type_int
.max_value
;
39 if (cptr
->info
->get_max_value
) {
40 cptr
->info
->get_max_value(cptr
,&lim
);
42 if (val
> lim
) return -ERANGE
;
48 /* Set the given control. */
49 int pvr2_ctrl_set_value(struct pvr2_ctrl
*cptr
,int val
)
51 return pvr2_ctrl_set_mask_value(cptr
,~0,val
);
55 /* Set/clear specific bits of the given control. */
56 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl
*cptr
,int mask
,int val
)
59 if (!cptr
) return -EINVAL
;
60 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
61 if (cptr
->info
->set_value
) {
62 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
63 mask
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
64 } else if ((cptr
->info
->type
== pvr2_ctl_int
)||
65 (cptr
->info
->type
== pvr2_ctl_enum
)) {
66 ret
= pvr2_ctrl_range_check(cptr
,val
);
68 } else if (cptr
->info
->type
!= pvr2_ctl_bool
) {
71 ret
= cptr
->info
->set_value(cptr
,mask
,val
);
75 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
80 /* Get the current value of the given control. */
81 int pvr2_ctrl_get_value(struct pvr2_ctrl
*cptr
,int *valptr
)
84 if (!cptr
) return -EINVAL
;
85 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
86 ret
= cptr
->info
->get_value(cptr
,valptr
);
87 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
92 /* Retrieve control's type */
93 enum pvr2_ctl_type
pvr2_ctrl_get_type(struct pvr2_ctrl
*cptr
)
95 if (!cptr
) return pvr2_ctl_int
;
96 return cptr
->info
->type
;
100 /* Retrieve control's maximum value (int type) */
101 int pvr2_ctrl_get_max(struct pvr2_ctrl
*cptr
)
105 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
106 if (cptr
->info
->get_max_value
) {
107 cptr
->info
->get_max_value(cptr
,&ret
);
108 } else if (cptr
->info
->type
== pvr2_ctl_int
) {
109 ret
= cptr
->info
->def
.type_int
.max_value
;
111 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
116 /* Retrieve control's minimum value (int type) */
117 int pvr2_ctrl_get_min(struct pvr2_ctrl
*cptr
)
121 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
122 if (cptr
->info
->get_min_value
) {
123 cptr
->info
->get_min_value(cptr
,&ret
);
124 } else if (cptr
->info
->type
== pvr2_ctl_int
) {
125 ret
= cptr
->info
->def
.type_int
.min_value
;
127 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
132 /* Retrieve control's default value (any type) */
133 int pvr2_ctrl_get_def(struct pvr2_ctrl
*cptr
, int *valptr
)
136 if (!cptr
) return -EINVAL
;
137 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
138 if (cptr
->info
->get_def_value
) {
139 ret
= cptr
->info
->get_def_value(cptr
, valptr
);
141 *valptr
= cptr
->info
->default_value
;
143 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
148 /* Retrieve control's enumeration count (enum only) */
149 int pvr2_ctrl_get_cnt(struct pvr2_ctrl
*cptr
)
153 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
154 if (cptr
->info
->type
== pvr2_ctl_enum
) {
155 ret
= cptr
->info
->def
.type_enum
.count
;
157 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
162 /* Retrieve control's valid mask bits (bit mask only) */
163 int pvr2_ctrl_get_mask(struct pvr2_ctrl
*cptr
)
167 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
168 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
169 ret
= cptr
->info
->def
.type_bitmask
.valid_bits
;
171 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
176 /* Retrieve the control's name */
177 const char *pvr2_ctrl_get_name(struct pvr2_ctrl
*cptr
)
179 if (!cptr
) return NULL
;
180 return cptr
->info
->name
;
184 /* Retrieve the control's desc */
185 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl
*cptr
)
187 if (!cptr
) return NULL
;
188 return cptr
->info
->desc
;
192 /* Retrieve a control enumeration or bit mask value */
193 int pvr2_ctrl_get_valname(struct pvr2_ctrl
*cptr
,int val
,
194 char *bptr
,unsigned int bmax
,
200 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
201 if (cptr
->info
->type
== pvr2_ctl_enum
) {
202 const char * const *names
;
203 names
= cptr
->info
->def
.type_enum
.value_names
;
204 if (pvr2_ctrl_range_check(cptr
,val
) == 0) {
214 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
218 names
= cptr
->info
->def
.type_bitmask
.bit_names
;
219 val
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
220 for (idx
= 0, msk
= 1; val
; idx
++, msk
<<= 1) {
222 *blen
= scnprintf(bptr
,bmax
,"%s",
229 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
234 /* Return V4L ID for this control or zero if none */
235 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl
*cptr
)
238 return cptr
->info
->v4l_id
;
242 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl
*cptr
)
244 unsigned int flags
= 0;
246 if (cptr
->info
->get_v4lflags
) {
247 flags
= cptr
->info
->get_v4lflags(cptr
);
250 if (cptr
->info
->set_value
) {
251 flags
&= ~V4L2_CTRL_FLAG_READ_ONLY
;
253 flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
260 /* Return true if control is writable */
261 int pvr2_ctrl_is_writable(struct pvr2_ctrl
*cptr
)
264 return cptr
->info
->set_value
!= NULL
;
268 /* Return true if control has custom symbolic representation */
269 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl
*cptr
)
272 if (!cptr
->info
->val_to_sym
) return 0;
273 if (!cptr
->info
->sym_to_val
) return 0;
278 /* Convert a given mask/val to a custom symbolic value */
279 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl
*cptr
,
281 char *buf
,unsigned int maxlen
,
284 if (!cptr
) return -EINVAL
;
285 if (!cptr
->info
->val_to_sym
) return -EINVAL
;
286 return cptr
->info
->val_to_sym(cptr
,mask
,val
,buf
,maxlen
,len
);
290 /* Convert a symbolic value to a mask/value pair */
291 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl
*cptr
,
292 const char *buf
,unsigned int len
,
293 int *maskptr
,int *valptr
)
295 if (!cptr
) return -EINVAL
;
296 if (!cptr
->info
->sym_to_val
) return -EINVAL
;
297 return cptr
->info
->sym_to_val(cptr
,buf
,len
,maskptr
,valptr
);
301 static unsigned int gen_bitmask_string(int msk
,int val
,int msk_only
,
303 char *ptr
,unsigned int len
)
314 for (idx
= 0, sm
= 1; msk
; idx
++, sm
<<= 1) {
319 cnt
= scnprintf(ptr
,len
,"%s%s%s",
322 ((val
& sm
) ? "+" : "-")),
324 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
333 cnt
= scnprintf(ptr
,len
,"%s0x%lx",
336 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
338 } else if (um
& val
) {
339 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
342 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
344 } else if (um
& ~val
) {
345 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
348 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
356 static const char *boolNames
[] = {
364 static int parse_token(const char *ptr
,unsigned int len
,
366 const char * const *names
, unsigned int namecnt
)
374 if (!names
) namecnt
= 0;
375 for (idx
= 0; idx
< namecnt
; idx
++) {
376 if (!names
[idx
]) continue;
377 slen
= strlen(names
[idx
]);
378 if (slen
!= len
) continue;
379 if (memcmp(names
[idx
],ptr
,slen
)) continue;
384 if ((*ptr
== '-') || (*ptr
== '+')) {
385 negfl
= (*ptr
== '-');
388 if (len
>= sizeof(buf
)) return -EINVAL
;
391 *valptr
= simple_strtol(buf
,&p2
,0);
392 if (negfl
) *valptr
= -(*valptr
);
393 if (*p2
) return -EINVAL
;
398 static int parse_mtoken(const char *ptr
,unsigned int len
,
400 const char **names
,int valid_bits
)
408 for (idx
= 0, msk
= 1; valid_bits
; idx
++, msk
<<= 1) {
409 if (!(msk
& valid_bits
)) continue;
411 if (!names
[idx
]) continue;
412 slen
= strlen(names
[idx
]);
413 if (slen
!= len
) continue;
414 if (memcmp(names
[idx
],ptr
,slen
)) continue;
418 if (len
>= sizeof(buf
)) return -EINVAL
;
421 *valptr
= simple_strtol(buf
,&p2
,0);
422 if (*p2
) return -EINVAL
;
427 static int parse_tlist(const char *ptr
,unsigned int len
,
428 int *maskptr
,int *valptr
,
429 const char **names
,int valid_bits
)
432 int mask
,val
,kv
,mode
,ret
;
438 while ((cnt
< len
) &&
440 (ptr
[cnt
] >= 127))) cnt
++;
444 if ((*ptr
== '-') || (*ptr
== '+')) {
445 mode
= (*ptr
== '-') ? -1 : 1;
451 if (ptr
[cnt
] <= 32) break;
452 if (ptr
[cnt
] >= 127) break;
456 if (parse_mtoken(ptr
,cnt
,&kv
,names
,valid_bits
)) {
485 /* Convert a symbolic value to a mask/value pair */
486 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl
*cptr
,
487 const char *ptr
,unsigned int len
,
488 int *maskptr
,int *valptr
)
497 while ((cnt
< len
) && ((ptr
[cnt
] <= 32) || (ptr
[cnt
] >= 127))) cnt
++;
498 len
-= cnt
; ptr
+= cnt
;
500 while ((cnt
< len
) && ((ptr
[len
-(cnt
+1)] <= 32) ||
501 (ptr
[len
-(cnt
+1)] >= 127))) cnt
++;
504 if (!len
) return -EINVAL
;
506 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
507 if (cptr
->info
->type
== pvr2_ctl_int
) {
508 ret
= parse_token(ptr
,len
,valptr
,NULL
,0);
510 ret
= pvr2_ctrl_range_check(cptr
,*valptr
);
513 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
514 ret
= parse_token(ptr
,len
,valptr
,boolNames
,
515 ARRAY_SIZE(boolNames
));
517 *valptr
= *valptr
? !0 : 0;
518 } else if (ret
== 0) {
519 *valptr
= (*valptr
& 1) ? !0 : 0;
522 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
525 cptr
->info
->def
.type_enum
.value_names
,
526 cptr
->info
->def
.type_enum
.count
);
528 ret
= pvr2_ctrl_range_check(cptr
,*valptr
);
531 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
533 ptr
,len
,maskptr
,valptr
,
534 cptr
->info
->def
.type_bitmask
.bit_names
,
535 cptr
->info
->def
.type_bitmask
.valid_bits
);
537 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
542 /* Convert a given mask/val to a symbolic value */
543 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl
*cptr
,
545 char *buf
,unsigned int maxlen
,
551 if (cptr
->info
->type
== pvr2_ctl_int
) {
552 *len
= scnprintf(buf
,maxlen
,"%d",val
);
554 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
555 *len
= scnprintf(buf
,maxlen
,"%s",val
? "true" : "false");
557 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
558 const char * const *names
;
559 names
= cptr
->info
->def
.type_enum
.value_names
;
561 (val
< cptr
->info
->def
.type_enum
.count
)) {
571 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
572 *len
= gen_bitmask_string(
573 val
& mask
& cptr
->info
->def
.type_bitmask
.valid_bits
,
575 cptr
->info
->def
.type_bitmask
.bit_names
,
582 /* Convert a given mask/val to a symbolic value */
583 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl
*cptr
,
585 char *buf
,unsigned int maxlen
,
589 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
590 ret
= pvr2_ctrl_value_to_sym_internal(cptr
,mask
,val
,
592 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);