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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "pvrusb2-ctrl.h"
22 #include "pvrusb2-hdw-internal.h"
23 #include <linux/errno.h>
24 #include <linux/string.h>
25 #include <linux/mutex.h>
28 static int pvr2_ctrl_range_check(struct pvr2_ctrl
*cptr
,int val
)
30 if (cptr
->info
->check_value
) {
31 if (!cptr
->info
->check_value(cptr
,val
)) return -ERANGE
;
32 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
33 if (val
< 0) return -ERANGE
;
34 if (val
>= cptr
->info
->def
.type_enum
.count
) return -ERANGE
;
37 lim
= cptr
->info
->def
.type_int
.min_value
;
38 if (cptr
->info
->get_min_value
) {
39 cptr
->info
->get_min_value(cptr
,&lim
);
41 if (val
< lim
) return -ERANGE
;
42 lim
= cptr
->info
->def
.type_int
.max_value
;
43 if (cptr
->info
->get_max_value
) {
44 cptr
->info
->get_max_value(cptr
,&lim
);
46 if (val
> lim
) return -ERANGE
;
52 /* Set the given control. */
53 int pvr2_ctrl_set_value(struct pvr2_ctrl
*cptr
,int val
)
55 return pvr2_ctrl_set_mask_value(cptr
,~0,val
);
59 /* Set/clear specific bits of the given control. */
60 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl
*cptr
,int mask
,int val
)
63 if (!cptr
) return -EINVAL
;
64 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
65 if (cptr
->info
->set_value
) {
66 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
67 mask
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
68 } else if ((cptr
->info
->type
== pvr2_ctl_int
)||
69 (cptr
->info
->type
== pvr2_ctl_enum
)) {
70 ret
= pvr2_ctrl_range_check(cptr
,val
);
72 } else if (cptr
->info
->type
!= pvr2_ctl_bool
) {
75 ret
= cptr
->info
->set_value(cptr
,mask
,val
);
79 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
84 /* Get the current value of the given control. */
85 int pvr2_ctrl_get_value(struct pvr2_ctrl
*cptr
,int *valptr
)
88 if (!cptr
) return -EINVAL
;
89 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
90 ret
= cptr
->info
->get_value(cptr
,valptr
);
91 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
96 /* Retrieve control's type */
97 enum pvr2_ctl_type
pvr2_ctrl_get_type(struct pvr2_ctrl
*cptr
)
99 if (!cptr
) return pvr2_ctl_int
;
100 return cptr
->info
->type
;
104 /* Retrieve control's maximum value (int type) */
105 int pvr2_ctrl_get_max(struct pvr2_ctrl
*cptr
)
109 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
110 if (cptr
->info
->get_max_value
) {
111 cptr
->info
->get_max_value(cptr
,&ret
);
112 } else if (cptr
->info
->type
== pvr2_ctl_int
) {
113 ret
= cptr
->info
->def
.type_int
.max_value
;
115 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
120 /* Retrieve control's minimum value (int type) */
121 int pvr2_ctrl_get_min(struct pvr2_ctrl
*cptr
)
125 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
126 if (cptr
->info
->get_min_value
) {
127 cptr
->info
->get_min_value(cptr
,&ret
);
128 } else if (cptr
->info
->type
== pvr2_ctl_int
) {
129 ret
= cptr
->info
->def
.type_int
.min_value
;
131 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
136 /* Retrieve control's default value (any type) */
137 int pvr2_ctrl_get_def(struct pvr2_ctrl
*cptr
, int *valptr
)
140 if (!cptr
) return -EINVAL
;
141 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
142 if (cptr
->info
->get_def_value
) {
143 ret
= cptr
->info
->get_def_value(cptr
, valptr
);
145 *valptr
= cptr
->info
->default_value
;
147 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
152 /* Retrieve control's enumeration count (enum only) */
153 int pvr2_ctrl_get_cnt(struct pvr2_ctrl
*cptr
)
157 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
158 if (cptr
->info
->type
== pvr2_ctl_enum
) {
159 ret
= cptr
->info
->def
.type_enum
.count
;
161 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
166 /* Retrieve control's valid mask bits (bit mask only) */
167 int pvr2_ctrl_get_mask(struct pvr2_ctrl
*cptr
)
171 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
172 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
173 ret
= cptr
->info
->def
.type_bitmask
.valid_bits
;
175 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
180 /* Retrieve the control's name */
181 const char *pvr2_ctrl_get_name(struct pvr2_ctrl
*cptr
)
183 if (!cptr
) return NULL
;
184 return cptr
->info
->name
;
188 /* Retrieve the control's desc */
189 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl
*cptr
)
191 if (!cptr
) return NULL
;
192 return cptr
->info
->desc
;
196 /* Retrieve a control enumeration or bit mask value */
197 int pvr2_ctrl_get_valname(struct pvr2_ctrl
*cptr
,int val
,
198 char *bptr
,unsigned int bmax
,
204 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
205 if (cptr
->info
->type
== pvr2_ctl_enum
) {
207 names
= cptr
->info
->def
.type_enum
.value_names
;
208 if (pvr2_ctrl_range_check(cptr
,val
) == 0) {
218 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
222 names
= cptr
->info
->def
.type_bitmask
.bit_names
;
223 val
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
224 for (idx
= 0, msk
= 1; val
; idx
++, msk
<<= 1) {
226 *blen
= scnprintf(bptr
,bmax
,"%s",
233 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
238 /* Return V4L ID for this control or zero if none */
239 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl
*cptr
)
242 return cptr
->info
->v4l_id
;
246 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl
*cptr
)
248 unsigned int flags
= 0;
250 if (cptr
->info
->get_v4lflags
) {
251 flags
= cptr
->info
->get_v4lflags(cptr
);
254 if (cptr
->info
->set_value
) {
255 flags
&= ~V4L2_CTRL_FLAG_READ_ONLY
;
257 flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
264 /* Return true if control is writable */
265 int pvr2_ctrl_is_writable(struct pvr2_ctrl
*cptr
)
268 return cptr
->info
->set_value
!= NULL
;
272 /* Return true if control has custom symbolic representation */
273 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl
*cptr
)
276 if (!cptr
->info
->val_to_sym
) return 0;
277 if (!cptr
->info
->sym_to_val
) return 0;
282 /* Convert a given mask/val to a custom symbolic value */
283 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl
*cptr
,
285 char *buf
,unsigned int maxlen
,
288 if (!cptr
) return -EINVAL
;
289 if (!cptr
->info
->val_to_sym
) return -EINVAL
;
290 return cptr
->info
->val_to_sym(cptr
,mask
,val
,buf
,maxlen
,len
);
294 /* Convert a symbolic value to a mask/value pair */
295 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl
*cptr
,
296 const char *buf
,unsigned int len
,
297 int *maskptr
,int *valptr
)
299 if (!cptr
) return -EINVAL
;
300 if (!cptr
->info
->sym_to_val
) return -EINVAL
;
301 return cptr
->info
->sym_to_val(cptr
,buf
,len
,maskptr
,valptr
);
305 static unsigned int gen_bitmask_string(int msk
,int val
,int msk_only
,
307 char *ptr
,unsigned int len
)
318 for (idx
= 0, sm
= 1; msk
; idx
++, sm
<<= 1) {
323 cnt
= scnprintf(ptr
,len
,"%s%s%s",
326 ((val
& sm
) ? "+" : "-")),
328 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
337 cnt
= scnprintf(ptr
,len
,"%s0x%lx",
340 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
342 } else if (um
& val
) {
343 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
346 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
348 } else if (um
& ~val
) {
349 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
352 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
360 static const char *boolNames
[] = {
368 static int parse_token(const char *ptr
,unsigned int len
,
370 const char **names
,unsigned int namecnt
)
378 if (!names
) namecnt
= 0;
379 for (idx
= 0; idx
< namecnt
; idx
++) {
380 if (!names
[idx
]) continue;
381 slen
= strlen(names
[idx
]);
382 if (slen
!= len
) continue;
383 if (memcmp(names
[idx
],ptr
,slen
)) continue;
388 if ((*ptr
== '-') || (*ptr
== '+')) {
389 negfl
= (*ptr
== '-');
392 if (len
>= sizeof(buf
)) return -EINVAL
;
395 *valptr
= simple_strtol(buf
,&p2
,0);
396 if (negfl
) *valptr
= -(*valptr
);
397 if (*p2
) return -EINVAL
;
402 static int parse_mtoken(const char *ptr
,unsigned int len
,
404 const char **names
,int valid_bits
)
412 for (idx
= 0, msk
= 1; valid_bits
; idx
++, msk
<<= 1) {
413 if (!(msk
& valid_bits
)) continue;
415 if (!names
[idx
]) continue;
416 slen
= strlen(names
[idx
]);
417 if (slen
!= len
) continue;
418 if (memcmp(names
[idx
],ptr
,slen
)) continue;
422 if (len
>= sizeof(buf
)) return -EINVAL
;
425 *valptr
= simple_strtol(buf
,&p2
,0);
426 if (*p2
) return -EINVAL
;
431 static int parse_tlist(const char *ptr
,unsigned int len
,
432 int *maskptr
,int *valptr
,
433 const char **names
,int valid_bits
)
436 int mask
,val
,kv
,mode
,ret
;
442 while ((cnt
< len
) &&
444 (ptr
[cnt
] >= 127))) cnt
++;
448 if ((*ptr
== '-') || (*ptr
== '+')) {
449 mode
= (*ptr
== '-') ? -1 : 1;
455 if (ptr
[cnt
] <= 32) break;
456 if (ptr
[cnt
] >= 127) break;
460 if (parse_mtoken(ptr
,cnt
,&kv
,names
,valid_bits
)) {
489 /* Convert a symbolic value to a mask/value pair */
490 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl
*cptr
,
491 const char *ptr
,unsigned int len
,
492 int *maskptr
,int *valptr
)
501 while ((cnt
< len
) && ((ptr
[cnt
] <= 32) || (ptr
[cnt
] >= 127))) cnt
++;
502 len
-= cnt
; ptr
+= cnt
;
504 while ((cnt
< len
) && ((ptr
[len
-(cnt
+1)] <= 32) ||
505 (ptr
[len
-(cnt
+1)] >= 127))) cnt
++;
508 if (!len
) return -EINVAL
;
510 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
511 if (cptr
->info
->type
== pvr2_ctl_int
) {
512 ret
= parse_token(ptr
,len
,valptr
,NULL
,0);
514 ret
= pvr2_ctrl_range_check(cptr
,*valptr
);
516 if (maskptr
) *maskptr
= ~0;
517 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
518 ret
= parse_token(ptr
,len
,valptr
,boolNames
,
519 ARRAY_SIZE(boolNames
));
521 *valptr
= *valptr
? !0 : 0;
522 } else if (ret
== 0) {
523 *valptr
= (*valptr
& 1) ? !0 : 0;
525 if (maskptr
) *maskptr
= 1;
526 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
529 cptr
->info
->def
.type_enum
.value_names
,
530 cptr
->info
->def
.type_enum
.count
);
532 ret
= pvr2_ctrl_range_check(cptr
,*valptr
);
534 if (maskptr
) *maskptr
= ~0;
535 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
537 ptr
,len
,maskptr
,valptr
,
538 cptr
->info
->def
.type_bitmask
.bit_names
,
539 cptr
->info
->def
.type_bitmask
.valid_bits
);
541 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
546 /* Convert a given mask/val to a symbolic value */
547 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl
*cptr
,
549 char *buf
,unsigned int maxlen
,
555 if (cptr
->info
->type
== pvr2_ctl_int
) {
556 *len
= scnprintf(buf
,maxlen
,"%d",val
);
558 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
559 *len
= scnprintf(buf
,maxlen
,"%s",val
? "true" : "false");
561 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
563 names
= cptr
->info
->def
.type_enum
.value_names
;
565 (val
< cptr
->info
->def
.type_enum
.count
)) {
575 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
576 *len
= gen_bitmask_string(
577 val
& mask
& cptr
->info
->def
.type_bitmask
.valid_bits
,
579 cptr
->info
->def
.type_bitmask
.bit_names
,
586 /* Convert a given mask/val to a symbolic value */
587 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl
*cptr
,
589 char *buf
,unsigned int maxlen
,
593 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
594 ret
= pvr2_ctrl_value_to_sym_internal(cptr
,mask
,val
,
596 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
602 Stuff for Emacs to see, in order to encourage consistent editing style:
603 *** Local Variables: ***
605 *** fill-column: 75 ***
607 *** c-basic-offset: 8 ***