5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
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
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.
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
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>
29 static int pvr2_ctrl_range_check(struct pvr2_ctrl
*cptr
,int val
)
31 if (cptr
->info
->check_value
) {
32 if (!cptr
->info
->check_value(cptr
,val
)) return -ERANGE
;
33 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
34 if (val
< 0) return -ERANGE
;
35 if (val
>= cptr
->info
->def
.type_enum
.count
) return -ERANGE
;
38 lim
= cptr
->info
->def
.type_int
.min_value
;
39 if (cptr
->info
->get_min_value
) {
40 cptr
->info
->get_min_value(cptr
,&lim
);
42 if (val
< lim
) return -ERANGE
;
43 lim
= cptr
->info
->def
.type_int
.max_value
;
44 if (cptr
->info
->get_max_value
) {
45 cptr
->info
->get_max_value(cptr
,&lim
);
47 if (val
> lim
) return -ERANGE
;
53 /* Set the given control. */
54 int pvr2_ctrl_set_value(struct pvr2_ctrl
*cptr
,int val
)
56 return pvr2_ctrl_set_mask_value(cptr
,~0,val
);
60 /* Set/clear specific bits of the given control. */
61 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl
*cptr
,int mask
,int val
)
64 if (!cptr
) return -EINVAL
;
65 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
66 if (cptr
->info
->set_value
) {
67 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
68 mask
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
69 } else if ((cptr
->info
->type
== pvr2_ctl_int
)||
70 (cptr
->info
->type
== pvr2_ctl_enum
)) {
71 ret
= pvr2_ctrl_range_check(cptr
,val
);
73 } else if (cptr
->info
->type
!= pvr2_ctl_bool
) {
76 ret
= cptr
->info
->set_value(cptr
,mask
,val
);
80 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
85 /* Get the current value of the given control. */
86 int pvr2_ctrl_get_value(struct pvr2_ctrl
*cptr
,int *valptr
)
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
);
97 /* Retrieve control's type */
98 enum pvr2_ctl_type
pvr2_ctrl_get_type(struct pvr2_ctrl
*cptr
)
100 if (!cptr
) return pvr2_ctl_int
;
101 return cptr
->info
->type
;
105 /* Retrieve control's maximum value (int type) */
106 int pvr2_ctrl_get_max(struct pvr2_ctrl
*cptr
)
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
;
116 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
121 /* Retrieve control's minimum value (int type) */
122 int pvr2_ctrl_get_min(struct pvr2_ctrl
*cptr
)
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
;
132 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
137 /* Retrieve control's default value (any type) */
138 int pvr2_ctrl_get_def(struct pvr2_ctrl
*cptr
)
142 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
143 if (cptr
->info
->type
== pvr2_ctl_int
) {
144 ret
= cptr
->info
->default_value
;
146 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
151 /* Retrieve control's enumeration count (enum only) */
152 int pvr2_ctrl_get_cnt(struct pvr2_ctrl
*cptr
)
156 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
157 if (cptr
->info
->type
== pvr2_ctl_enum
) {
158 ret
= cptr
->info
->def
.type_enum
.count
;
160 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
165 /* Retrieve control's valid mask bits (bit mask only) */
166 int pvr2_ctrl_get_mask(struct pvr2_ctrl
*cptr
)
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
;
174 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
179 /* Retrieve the control's name */
180 const char *pvr2_ctrl_get_name(struct pvr2_ctrl
*cptr
)
182 if (!cptr
) return NULL
;
183 return cptr
->info
->name
;
187 /* Retrieve the control's desc */
188 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl
*cptr
)
190 if (!cptr
) return NULL
;
191 return cptr
->info
->desc
;
195 /* Retrieve a control enumeration or bit mask value */
196 int pvr2_ctrl_get_valname(struct pvr2_ctrl
*cptr
,int val
,
197 char *bptr
,unsigned int bmax
,
203 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
204 if (cptr
->info
->type
== pvr2_ctl_enum
) {
206 names
= cptr
->info
->def
.type_enum
.value_names
;
207 if (pvr2_ctrl_range_check(cptr
,val
) == 0) {
217 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
221 names
= cptr
->info
->def
.type_bitmask
.bit_names
;
222 val
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
223 for (idx
= 0, msk
= 1; val
; idx
++, msk
<<= 1) {
225 *blen
= scnprintf(bptr
,bmax
,"%s",
232 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
237 /* Return V4L ID for this control or zero if none */
238 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl
*cptr
)
241 return cptr
->info
->v4l_id
;
245 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl
*cptr
)
247 unsigned int flags
= 0;
249 if (cptr
->info
->get_v4lflags
) {
250 flags
= cptr
->info
->get_v4lflags(cptr
);
253 if (cptr
->info
->set_value
) {
254 flags
&= ~V4L2_CTRL_FLAG_READ_ONLY
;
256 flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
263 /* Return true if control is writable */
264 int pvr2_ctrl_is_writable(struct pvr2_ctrl
*cptr
)
267 return cptr
->info
->set_value
!= NULL
;
271 /* Return true if control has custom symbolic representation */
272 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl
*cptr
)
275 if (!cptr
->info
->val_to_sym
) return 0;
276 if (!cptr
->info
->sym_to_val
) return 0;
281 /* Convert a given mask/val to a custom symbolic value */
282 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl
*cptr
,
284 char *buf
,unsigned int maxlen
,
287 if (!cptr
) return -EINVAL
;
288 if (!cptr
->info
->val_to_sym
) return -EINVAL
;
289 return cptr
->info
->val_to_sym(cptr
,mask
,val
,buf
,maxlen
,len
);
293 /* Convert a symbolic value to a mask/value pair */
294 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl
*cptr
,
295 const char *buf
,unsigned int len
,
296 int *maskptr
,int *valptr
)
298 if (!cptr
) return -EINVAL
;
299 if (!cptr
->info
->sym_to_val
) return -EINVAL
;
300 return cptr
->info
->sym_to_val(cptr
,buf
,len
,maskptr
,valptr
);
304 static unsigned int gen_bitmask_string(int msk
,int val
,int msk_only
,
306 char *ptr
,unsigned int len
)
317 for (idx
= 0, sm
= 1; msk
; idx
++, sm
<<= 1) {
322 cnt
= scnprintf(ptr
,len
,"%s%s%s",
325 ((val
& sm
) ? "+" : "-")),
327 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
336 cnt
= scnprintf(ptr
,len
,"%s0x%lx",
339 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
341 } else if (um
& val
) {
342 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
345 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
347 } else if (um
& ~val
) {
348 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
351 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
359 static const char *boolNames
[] = {
367 static int parse_token(const char *ptr
,unsigned int len
,
369 const char **names
,unsigned int namecnt
)
377 if (!names
) namecnt
= 0;
378 for (idx
= 0; idx
< namecnt
; idx
++) {
379 if (!names
[idx
]) continue;
380 slen
= strlen(names
[idx
]);
381 if (slen
!= len
) continue;
382 if (memcmp(names
[idx
],ptr
,slen
)) continue;
387 if ((*ptr
== '-') || (*ptr
== '+')) {
388 negfl
= (*ptr
== '-');
391 if (len
>= sizeof(buf
)) return -EINVAL
;
394 *valptr
= simple_strtol(buf
,&p2
,0);
395 if (negfl
) *valptr
= -(*valptr
);
396 if (*p2
) return -EINVAL
;
401 static int parse_mtoken(const char *ptr
,unsigned int len
,
403 const char **names
,int valid_bits
)
411 for (idx
= 0, msk
= 1; valid_bits
; idx
++, msk
<<= 1) {
412 if (!(msk
& valid_bits
)) continue;
414 if (!names
[idx
]) continue;
415 slen
= strlen(names
[idx
]);
416 if (slen
!= len
) continue;
417 if (memcmp(names
[idx
],ptr
,slen
)) continue;
421 if (len
>= sizeof(buf
)) return -EINVAL
;
424 *valptr
= simple_strtol(buf
,&p2
,0);
425 if (*p2
) return -EINVAL
;
430 static int parse_tlist(const char *ptr
,unsigned int len
,
431 int *maskptr
,int *valptr
,
432 const char **names
,int valid_bits
)
435 int mask
,val
,kv
,mode
,ret
;
441 while ((cnt
< len
) &&
443 (ptr
[cnt
] >= 127))) cnt
++;
447 if ((*ptr
== '-') || (*ptr
== '+')) {
448 mode
= (*ptr
== '-') ? -1 : 1;
454 if (ptr
[cnt
] <= 32) break;
455 if (ptr
[cnt
] >= 127) break;
459 if (parse_mtoken(ptr
,cnt
,&kv
,names
,valid_bits
)) {
488 /* Convert a symbolic value to a mask/value pair */
489 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl
*cptr
,
490 const char *ptr
,unsigned int len
,
491 int *maskptr
,int *valptr
)
500 while ((cnt
< len
) && ((ptr
[cnt
] <= 32) || (ptr
[cnt
] >= 127))) cnt
++;
501 len
-= cnt
; ptr
+= cnt
;
503 while ((cnt
< len
) && ((ptr
[len
-(cnt
+1)] <= 32) ||
504 (ptr
[len
-(cnt
+1)] >= 127))) cnt
++;
507 if (!len
) return -EINVAL
;
509 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
510 if (cptr
->info
->type
== pvr2_ctl_int
) {
511 ret
= parse_token(ptr
,len
,valptr
,NULL
,0);
513 ret
= pvr2_ctrl_range_check(cptr
,*valptr
);
515 if (maskptr
) *maskptr
= ~0;
516 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
517 ret
= parse_token(ptr
,len
,valptr
,boolNames
,
518 ARRAY_SIZE(boolNames
));
520 *valptr
= *valptr
? !0 : 0;
521 } else if (ret
== 0) {
522 *valptr
= (*valptr
& 1) ? !0 : 0;
524 if (maskptr
) *maskptr
= 1;
525 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
528 cptr
->info
->def
.type_enum
.value_names
,
529 cptr
->info
->def
.type_enum
.count
);
531 ret
= pvr2_ctrl_range_check(cptr
,*valptr
);
533 if (maskptr
) *maskptr
= ~0;
534 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
536 ptr
,len
,maskptr
,valptr
,
537 cptr
->info
->def
.type_bitmask
.bit_names
,
538 cptr
->info
->def
.type_bitmask
.valid_bits
);
540 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
545 /* Convert a given mask/val to a symbolic value */
546 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl
*cptr
,
548 char *buf
,unsigned int maxlen
,
554 if (cptr
->info
->type
== pvr2_ctl_int
) {
555 *len
= scnprintf(buf
,maxlen
,"%d",val
);
557 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
558 *len
= scnprintf(buf
,maxlen
,"%s",val
? "true" : "false");
560 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
562 names
= cptr
->info
->def
.type_enum
.value_names
;
564 (val
< cptr
->info
->def
.type_enum
.count
)) {
574 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
575 *len
= gen_bitmask_string(
576 val
& mask
& cptr
->info
->def
.type_bitmask
.valid_bits
,
578 cptr
->info
->def
.type_bitmask
.bit_names
,
585 /* Convert a given mask/val to a symbolic value */
586 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl
*cptr
,
588 char *buf
,unsigned int maxlen
,
592 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
593 ret
= pvr2_ctrl_value_to_sym_internal(cptr
,mask
,val
,
595 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
601 Stuff for Emacs to see, in order to encourage consistent editing style:
602 *** Local Variables: ***
604 *** fill-column: 75 ***
606 *** c-basic-offset: 8 ***