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 ***