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)
141 LOCK_TAKE(cptr->hdw->big_lock); do {
142 if (cptr->info->type == pvr2_ctl_int) {
143 ret = cptr->info->default_value;
145 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
150 /* Retrieve control's enumeration count (enum only) */
151 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
155 LOCK_TAKE(cptr->hdw->big_lock); do {
156 if (cptr->info->type == pvr2_ctl_enum) {
157 ret = cptr->info->def.type_enum.count;
159 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
164 /* Retrieve control's valid mask bits (bit mask only) */
165 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
169 LOCK_TAKE(cptr->hdw->big_lock); do {
170 if (cptr->info->type == pvr2_ctl_bitmask) {
171 ret = cptr->info->def.type_bitmask.valid_bits;
173 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
178 /* Retrieve the control's name */
179 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
181 if (!cptr) return NULL;
182 return cptr->info->name;
186 /* Retrieve the control's desc */
187 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
189 if (!cptr) return NULL;
190 return cptr->info->desc;
194 /* Retrieve a control enumeration or bit mask value */
195 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
196 char *bptr,unsigned int bmax,
202 LOCK_TAKE(cptr->hdw->big_lock); do {
203 if (cptr->info->type == pvr2_ctl_enum) {
205 names = cptr->info->def.type_enum.value_names;
206 if (pvr2_ctrl_range_check(cptr,val) == 0) {
216 } else if (cptr->info->type == pvr2_ctl_bitmask) {
220 names = cptr->info->def.type_bitmask.bit_names;
221 val &= cptr->info->def.type_bitmask.valid_bits;
222 for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
224 *blen = scnprintf(bptr,bmax,"%s",
231 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
236 /* Return V4L ID for this control or zero if none */
237 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
240 return cptr->info->v4l_id;
244 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
246 unsigned int flags = 0;
248 if (cptr->info->get_v4lflags) {
249 flags = cptr->info->get_v4lflags(cptr);
252 if (cptr->info->set_value) {
253 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
255 flags |= V4L2_CTRL_FLAG_READ_ONLY;
262 /* Return true if control is writable */
263 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
266 return cptr->info->set_value != NULL;
270 /* Return true if control has custom symbolic representation */
271 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
274 if (!cptr->info->val_to_sym) return 0;
275 if (!cptr->info->sym_to_val) return 0;
280 /* Convert a given mask/val to a custom symbolic value */
281 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
283 char *buf,unsigned int maxlen,
286 if (!cptr) return -EINVAL;
287 if (!cptr->info->val_to_sym) return -EINVAL;
288 return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
292 /* Convert a symbolic value to a mask/value pair */
293 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
294 const char *buf,unsigned int len,
295 int *maskptr,int *valptr)
297 if (!cptr) return -EINVAL;
298 if (!cptr->info->sym_to_val) return -EINVAL;
299 return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
303 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
305 char *ptr,unsigned int len)
316 for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
321 cnt = scnprintf(ptr,len,"%s%s%s",
324 ((val & sm) ? "+" : "-")),
326 ptr += cnt; len -= cnt; uc += cnt;
335 cnt = scnprintf(ptr,len,"%s0x%lx",
338 ptr += cnt; len -= cnt; uc += cnt;
340 } else if (um & val) {
341 cnt = scnprintf(ptr,len,"%s+0x%lx",
344 ptr += cnt; len -= cnt; uc += cnt;
346 } else if (um & ~val) {
347 cnt = scnprintf(ptr,len,"%s+0x%lx",
350 ptr += cnt; len -= cnt; uc += cnt;
358 static const char *boolNames[] = {
366 static int parse_token(const char *ptr,unsigned int len,
368 const char **names,unsigned int namecnt)
376 if (!names) namecnt = 0;
377 for (idx = 0; idx < namecnt; idx++) {
378 if (!names[idx]) continue;
379 slen = strlen(names[idx]);
380 if (slen != len) continue;
381 if (memcmp(names[idx],ptr,slen)) continue;
386 if ((*ptr == '-') || (*ptr == '+')) {
387 negfl = (*ptr == '-');
390 if (len >= sizeof(buf)) return -EINVAL;
393 *valptr = simple_strtol(buf,&p2,0);
394 if (negfl) *valptr = -(*valptr);
395 if (*p2) return -EINVAL;
400 static int parse_mtoken(const char *ptr,unsigned int len,
402 const char **names,int valid_bits)
410 for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
411 if (!(msk & valid_bits)) continue;
413 if (!names[idx]) continue;
414 slen = strlen(names[idx]);
415 if (slen != len) continue;
416 if (memcmp(names[idx],ptr,slen)) continue;
420 if (len >= sizeof(buf)) return -EINVAL;
423 *valptr = simple_strtol(buf,&p2,0);
424 if (*p2) return -EINVAL;
429 static int parse_tlist(const char *ptr,unsigned int len,
430 int *maskptr,int *valptr,
431 const char **names,int valid_bits)
434 int mask,val,kv,mode,ret;
440 while ((cnt < len) &&
442 (ptr[cnt] >= 127))) cnt++;
446 if ((*ptr == '-') || (*ptr == '+')) {
447 mode = (*ptr == '-') ? -1 : 1;
453 if (ptr[cnt] <= 32) break;
454 if (ptr[cnt] >= 127) break;
458 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
487 /* Convert a symbolic value to a mask/value pair */
488 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
489 const char *ptr,unsigned int len,
490 int *maskptr,int *valptr)
499 while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
500 len -= cnt; ptr += cnt;
502 while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
503 (ptr[len-(cnt+1)] >= 127))) cnt++;
506 if (!len) return -EINVAL;
508 LOCK_TAKE(cptr->hdw->big_lock); do {
509 if (cptr->info->type == pvr2_ctl_int) {
510 ret = parse_token(ptr,len,valptr,NULL,0);
512 ret = pvr2_ctrl_range_check(cptr,*valptr);
514 if (maskptr) *maskptr = ~0;
515 } else if (cptr->info->type == pvr2_ctl_bool) {
516 ret = parse_token(ptr,len,valptr,boolNames,
517 ARRAY_SIZE(boolNames));
519 *valptr = *valptr ? !0 : 0;
520 } else if (ret == 0) {
521 *valptr = (*valptr & 1) ? !0 : 0;
523 if (maskptr) *maskptr = 1;
524 } else if (cptr->info->type == pvr2_ctl_enum) {
527 cptr->info->def.type_enum.value_names,
528 cptr->info->def.type_enum.count);
530 ret = pvr2_ctrl_range_check(cptr,*valptr);
532 if (maskptr) *maskptr = ~0;
533 } else if (cptr->info->type == pvr2_ctl_bitmask) {
535 ptr,len,maskptr,valptr,
536 cptr->info->def.type_bitmask.bit_names,
537 cptr->info->def.type_bitmask.valid_bits);
539 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
544 /* Convert a given mask/val to a symbolic value */
545 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
547 char *buf,unsigned int maxlen,
553 if (cptr->info->type == pvr2_ctl_int) {
554 *len = scnprintf(buf,maxlen,"%d",val);
556 } else if (cptr->info->type == pvr2_ctl_bool) {
557 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
559 } else if (cptr->info->type == pvr2_ctl_enum) {
561 names = cptr->info->def.type_enum.value_names;
563 (val < cptr->info->def.type_enum.count)) {
573 } else if (cptr->info->type == pvr2_ctl_bitmask) {
574 *len = gen_bitmask_string(
575 val & mask & cptr->info->def.type_bitmask.valid_bits,
577 cptr->info->def.type_bitmask.bit_names,
584 /* Convert a given mask/val to a symbolic value */
585 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
587 char *buf,unsigned int maxlen,
591 LOCK_TAKE(cptr->hdw->big_lock); do {
592 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
594 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
600 Stuff for Emacs to see, in order to encourage consistent editing style:
601 *** Local Variables: ***
603 *** fill-column: 75 ***
605 *** c-basic-offset: 8 ***