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 /* Set the given control. */
30 int pvr2_ctrl_set_value(struct pvr2_ctrl
*cptr
,int val
)
32 return pvr2_ctrl_set_mask_value(cptr
,~0,val
);
36 /* Set/clear specific bits of the given control. */
37 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl
*cptr
,int mask
,int val
)
40 if (!cptr
) return -EINVAL
;
41 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
42 if (cptr
->info
->set_value
!= 0) {
43 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
44 mask
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
45 } else if (cptr
->info
->type
== pvr2_ctl_int
) {
46 if (val
< cptr
->info
->def
.type_int
.min_value
) {
49 if (val
> cptr
->info
->def
.type_int
.max_value
) {
52 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
53 if (val
>= cptr
->info
->def
.type_enum
.count
) {
56 } else if (cptr
->info
->type
!= pvr2_ctl_bool
) {
59 ret
= cptr
->info
->set_value(cptr
,mask
,val
);
63 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
68 /* Get the current value of the given control. */
69 int pvr2_ctrl_get_value(struct pvr2_ctrl
*cptr
,int *valptr
)
72 if (!cptr
) return -EINVAL
;
73 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
74 ret
= cptr
->info
->get_value(cptr
,valptr
);
75 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
80 /* Retrieve control's type */
81 enum pvr2_ctl_type
pvr2_ctrl_get_type(struct pvr2_ctrl
*cptr
)
83 if (!cptr
) return pvr2_ctl_int
;
84 return cptr
->info
->type
;
88 /* Retrieve control's maximum value (int type) */
89 int pvr2_ctrl_get_max(struct pvr2_ctrl
*cptr
)
93 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
94 if (cptr
->info
->type
== pvr2_ctl_int
) {
95 ret
= cptr
->info
->def
.type_int
.max_value
;
97 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
102 /* Retrieve control's minimum value (int type) */
103 int pvr2_ctrl_get_min(struct pvr2_ctrl
*cptr
)
107 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
108 if (cptr
->info
->type
== pvr2_ctl_int
) {
109 ret
= cptr
->info
->def
.type_int
.min_value
;
111 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
116 /* Retrieve control's default value (any type) */
117 int pvr2_ctrl_get_def(struct pvr2_ctrl
*cptr
)
121 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
122 if (cptr
->info
->type
== pvr2_ctl_int
) {
123 ret
= cptr
->info
->default_value
;
125 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
130 /* Retrieve control's enumeration count (enum only) */
131 int pvr2_ctrl_get_cnt(struct pvr2_ctrl
*cptr
)
135 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
136 if (cptr
->info
->type
== pvr2_ctl_enum
) {
137 ret
= cptr
->info
->def
.type_enum
.count
;
139 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
144 /* Retrieve control's valid mask bits (bit mask only) */
145 int pvr2_ctrl_get_mask(struct pvr2_ctrl
*cptr
)
149 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
150 if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
151 ret
= cptr
->info
->def
.type_bitmask
.valid_bits
;
153 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
158 /* Retrieve the control's name */
159 const char *pvr2_ctrl_get_name(struct pvr2_ctrl
*cptr
)
161 if (!cptr
) return NULL
;
162 return cptr
->info
->name
;
166 /* Retrieve the control's desc */
167 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl
*cptr
)
169 if (!cptr
) return NULL
;
170 return cptr
->info
->desc
;
174 /* Retrieve a control enumeration or bit mask value */
175 int pvr2_ctrl_get_valname(struct pvr2_ctrl
*cptr
,int val
,
176 char *bptr
,unsigned int bmax
,
182 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
183 if (cptr
->info
->type
== pvr2_ctl_enum
) {
185 names
= cptr
->info
->def
.type_enum
.value_names
;
187 (val
< cptr
->info
->def
.type_enum
.count
)) {
197 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
201 names
= cptr
->info
->def
.type_bitmask
.bit_names
;
202 val
&= cptr
->info
->def
.type_bitmask
.valid_bits
;
203 for (idx
= 0, msk
= 1; val
; idx
++, msk
<<= 1) {
205 *blen
= scnprintf(bptr
,bmax
,"%s",
212 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
217 /* Return V4L ID for this control or zero if none */
218 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl
*cptr
)
221 return cptr
->info
->v4l_id
;
225 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl
*cptr
)
227 unsigned int flags
= 0;
229 if (cptr
->info
->get_v4lflags
) {
230 flags
= cptr
->info
->get_v4lflags(cptr
);
233 if (cptr
->info
->set_value
) {
234 flags
&= ~V4L2_CTRL_FLAG_READ_ONLY
;
236 flags
|= V4L2_CTRL_FLAG_READ_ONLY
;
243 /* Return true if control is writable */
244 int pvr2_ctrl_is_writable(struct pvr2_ctrl
*cptr
)
247 return cptr
->info
->set_value
!= 0;
251 /* Return true if control has custom symbolic representation */
252 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl
*cptr
)
255 if (!cptr
->info
->val_to_sym
) return 0;
256 if (!cptr
->info
->sym_to_val
) return 0;
261 /* Convert a given mask/val to a custom symbolic value */
262 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl
*cptr
,
264 char *buf
,unsigned int maxlen
,
267 if (!cptr
) return -EINVAL
;
268 if (!cptr
->info
->val_to_sym
) return -EINVAL
;
269 return cptr
->info
->val_to_sym(cptr
,mask
,val
,buf
,maxlen
,len
);
273 /* Convert a symbolic value to a mask/value pair */
274 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl
*cptr
,
275 const char *buf
,unsigned int len
,
276 int *maskptr
,int *valptr
)
278 if (!cptr
) return -EINVAL
;
279 if (!cptr
->info
->sym_to_val
) return -EINVAL
;
280 return cptr
->info
->sym_to_val(cptr
,buf
,len
,maskptr
,valptr
);
284 static unsigned int gen_bitmask_string(int msk
,int val
,int msk_only
,
286 char *ptr
,unsigned int len
)
297 for (idx
= 0, sm
= 1; msk
; idx
++, sm
<<= 1) {
302 cnt
= scnprintf(ptr
,len
,"%s%s%s",
305 ((val
& sm
) ? "+" : "-")),
307 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
316 cnt
= scnprintf(ptr
,len
,"%s0x%lx",
319 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
321 } else if (um
& val
) {
322 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
325 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
327 } else if (um
& ~val
) {
328 cnt
= scnprintf(ptr
,len
,"%s+0x%lx",
331 ptr
+= cnt
; len
-= cnt
; uc
+= cnt
;
339 static const char *boolNames
[] = {
347 static int parse_token(const char *ptr
,unsigned int len
,
349 const char **names
,unsigned int namecnt
)
357 if (!names
) namecnt
= 0;
358 for (idx
= 0; idx
< namecnt
; idx
++) {
359 if (!names
[idx
]) continue;
360 slen
= strlen(names
[idx
]);
361 if (slen
!= len
) continue;
362 if (memcmp(names
[idx
],ptr
,slen
)) continue;
367 if ((*ptr
== '-') || (*ptr
== '+')) {
368 negfl
= (*ptr
== '-');
371 if (len
>= sizeof(buf
)) return -EINVAL
;
374 *valptr
= simple_strtol(buf
,&p2
,0);
375 if (negfl
) *valptr
= -(*valptr
);
376 if (*p2
) return -EINVAL
;
381 static int parse_mtoken(const char *ptr
,unsigned int len
,
383 const char **names
,int valid_bits
)
391 for (idx
= 0, msk
= 1; valid_bits
; idx
++, msk
<<= 1) {
392 if (!msk
& valid_bits
) continue;
394 if (!names
[idx
]) continue;
395 slen
= strlen(names
[idx
]);
396 if (slen
!= len
) continue;
397 if (memcmp(names
[idx
],ptr
,slen
)) continue;
401 if (len
>= sizeof(buf
)) return -EINVAL
;
404 *valptr
= simple_strtol(buf
,&p2
,0);
405 if (*p2
) return -EINVAL
;
410 static int parse_tlist(const char *ptr
,unsigned int len
,
411 int *maskptr
,int *valptr
,
412 const char **names
,int valid_bits
)
415 int mask
,val
,kv
,mode
,ret
;
421 while ((cnt
< len
) &&
423 (ptr
[cnt
] >= 127))) cnt
++;
427 if ((*ptr
== '-') || (*ptr
== '+')) {
428 mode
= (*ptr
== '-') ? -1 : 1;
434 if (ptr
[cnt
] <= 32) break;
435 if (ptr
[cnt
] >= 127) break;
439 if (parse_mtoken(ptr
,cnt
,&kv
,names
,valid_bits
)) {
468 /* Convert a symbolic value to a mask/value pair */
469 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl
*cptr
,
470 const char *ptr
,unsigned int len
,
471 int *maskptr
,int *valptr
)
480 while ((cnt
< len
) && ((ptr
[cnt
] <= 32) || (ptr
[cnt
] >= 127))) cnt
++;
481 len
-= cnt
; ptr
+= cnt
;
483 while ((cnt
< len
) && ((ptr
[len
-(cnt
+1)] <= 32) ||
484 (ptr
[len
-(cnt
+1)] >= 127))) cnt
++;
487 if (!len
) return -EINVAL
;
489 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
490 if (cptr
->info
->type
== pvr2_ctl_int
) {
491 ret
= parse_token(ptr
,len
,valptr
,NULL
,0);
493 ((*valptr
< cptr
->info
->def
.type_int
.min_value
) ||
494 (*valptr
> cptr
->info
->def
.type_int
.max_value
))) {
497 if (maskptr
) *maskptr
= ~0;
498 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
500 ptr
,len
,valptr
,boolNames
,
501 sizeof(boolNames
)/sizeof(boolNames
[0]));
503 *valptr
= *valptr
? !0 : 0;
504 } else if (ret
== 0) {
505 *valptr
= (*valptr
& 1) ? !0 : 0;
507 if (maskptr
) *maskptr
= 1;
508 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
511 cptr
->info
->def
.type_enum
.value_names
,
512 cptr
->info
->def
.type_enum
.count
);
515 (*valptr
>= cptr
->info
->def
.type_enum
.count
))) {
518 if (maskptr
) *maskptr
= ~0;
519 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
521 ptr
,len
,maskptr
,valptr
,
522 cptr
->info
->def
.type_bitmask
.bit_names
,
523 cptr
->info
->def
.type_bitmask
.valid_bits
);
525 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
530 /* Convert a given mask/val to a symbolic value */
531 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl
*cptr
,
533 char *buf
,unsigned int maxlen
,
539 if (cptr
->info
->type
== pvr2_ctl_int
) {
540 *len
= scnprintf(buf
,maxlen
,"%d",val
);
542 } else if (cptr
->info
->type
== pvr2_ctl_bool
) {
543 *len
= scnprintf(buf
,maxlen
,"%s",val
? "true" : "false");
545 } else if (cptr
->info
->type
== pvr2_ctl_enum
) {
547 names
= cptr
->info
->def
.type_enum
.value_names
;
549 (val
< cptr
->info
->def
.type_enum
.count
)) {
559 } else if (cptr
->info
->type
== pvr2_ctl_bitmask
) {
560 *len
= gen_bitmask_string(
561 val
& mask
& cptr
->info
->def
.type_bitmask
.valid_bits
,
563 cptr
->info
->def
.type_bitmask
.bit_names
,
570 /* Convert a given mask/val to a symbolic value */
571 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl
*cptr
,
573 char *buf
,unsigned int maxlen
,
577 LOCK_TAKE(cptr
->hdw
->big_lock
); do {
578 ret
= pvr2_ctrl_value_to_sym_internal(cptr
,mask
,val
,
580 } while(0); LOCK_GIVE(cptr
->hdw
->big_lock
);
586 Stuff for Emacs to see, in order to encourage consistent editing style:
587 *** Local Variables: ***
589 *** fill-column: 75 ***
591 *** c-basic-offset: 8 ***