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.
17 #include "pvrusb2-ctrl.h"
18 #include "pvrusb2-hdw-internal.h"
19 #include <linux/errno.h>
20 #include <linux/string.h>
21 #include <linux/mutex.h>
24 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
26 if (cptr->info->check_value) {
27 if (!cptr->info->check_value(cptr,val)) return -ERANGE;
28 } else if (cptr->info->type == pvr2_ctl_enum) {
29 if (val < 0) return -ERANGE;
30 if (val >= cptr->info->def.type_enum.count) return -ERANGE;
33 lim = cptr->info->def.type_int.min_value;
34 if (cptr->info->get_min_value) {
35 cptr->info->get_min_value(cptr,&lim);
37 if (val < lim) return -ERANGE;
38 lim = cptr->info->def.type_int.max_value;
39 if (cptr->info->get_max_value) {
40 cptr->info->get_max_value(cptr,&lim);
42 if (val > lim) return -ERANGE;
48 /* Set the given control. */
49 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
51 return pvr2_ctrl_set_mask_value(cptr,~0,val);
55 /* Set/clear specific bits of the given control. */
56 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
59 if (!cptr) return -EINVAL;
60 LOCK_TAKE(cptr->hdw->big_lock); do {
61 if (cptr->info->set_value) {
62 if (cptr->info->type == pvr2_ctl_bitmask) {
63 mask &= cptr->info->def.type_bitmask.valid_bits;
64 } else if ((cptr->info->type == pvr2_ctl_int)||
65 (cptr->info->type == pvr2_ctl_enum)) {
66 ret = pvr2_ctrl_range_check(cptr,val);
68 } else if (cptr->info->type != pvr2_ctl_bool) {
71 ret = cptr->info->set_value(cptr,mask,val);
75 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
80 /* Get the current value of the given control. */
81 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
84 if (!cptr) return -EINVAL;
85 LOCK_TAKE(cptr->hdw->big_lock); do {
86 ret = cptr->info->get_value(cptr,valptr);
87 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
92 /* Retrieve control's type */
93 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
95 if (!cptr) return pvr2_ctl_int;
96 return cptr->info->type;
100 /* Retrieve control's maximum value (int type) */
101 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
105 LOCK_TAKE(cptr->hdw->big_lock); do {
106 if (cptr->info->get_max_value) {
107 cptr->info->get_max_value(cptr,&ret);
108 } else if (cptr->info->type == pvr2_ctl_int) {
109 ret = cptr->info->def.type_int.max_value;
111 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
116 /* Retrieve control's minimum value (int type) */
117 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
121 LOCK_TAKE(cptr->hdw->big_lock); do {
122 if (cptr->info->get_min_value) {
123 cptr->info->get_min_value(cptr,&ret);
124 } else if (cptr->info->type == pvr2_ctl_int) {
125 ret = cptr->info->def.type_int.min_value;
127 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
132 /* Retrieve control's default value (any type) */
133 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
136 if (!cptr) return -EINVAL;
137 LOCK_TAKE(cptr->hdw->big_lock); do {
138 if (cptr->info->get_def_value) {
139 ret = cptr->info->get_def_value(cptr, valptr);
141 *valptr = cptr->info->default_value;
143 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
148 /* Retrieve control's enumeration count (enum only) */
149 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
153 LOCK_TAKE(cptr->hdw->big_lock); do {
154 if (cptr->info->type == pvr2_ctl_enum) {
155 ret = cptr->info->def.type_enum.count;
157 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
162 /* Retrieve control's valid mask bits (bit mask only) */
163 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
167 LOCK_TAKE(cptr->hdw->big_lock); do {
168 if (cptr->info->type == pvr2_ctl_bitmask) {
169 ret = cptr->info->def.type_bitmask.valid_bits;
171 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
176 /* Retrieve the control's name */
177 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
179 if (!cptr) return NULL;
180 return cptr->info->name;
184 /* Retrieve the control's desc */
185 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
187 if (!cptr) return NULL;
188 return cptr->info->desc;
192 /* Retrieve a control enumeration or bit mask value */
193 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
194 char *bptr,unsigned int bmax,
200 LOCK_TAKE(cptr->hdw->big_lock); do {
201 if (cptr->info->type == pvr2_ctl_enum) {
202 const char * const *names;
203 names = cptr->info->def.type_enum.value_names;
204 if (pvr2_ctrl_range_check(cptr,val) == 0) {
214 } else if (cptr->info->type == pvr2_ctl_bitmask) {
218 names = cptr->info->def.type_bitmask.bit_names;
219 val &= cptr->info->def.type_bitmask.valid_bits;
220 for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
222 *blen = scnprintf(bptr,bmax,"%s",
229 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
234 /* Return V4L ID for this control or zero if none */
235 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
238 return cptr->info->v4l_id;
242 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
244 unsigned int flags = 0;
246 if (cptr->info->get_v4lflags) {
247 flags = cptr->info->get_v4lflags(cptr);
250 if (cptr->info->set_value) {
251 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
253 flags |= V4L2_CTRL_FLAG_READ_ONLY;
260 /* Return true if control is writable */
261 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
264 return cptr->info->set_value != NULL;
268 /* Return true if control has custom symbolic representation */
269 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
272 if (!cptr->info->val_to_sym) return 0;
273 if (!cptr->info->sym_to_val) return 0;
278 /* Convert a given mask/val to a custom symbolic value */
279 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
281 char *buf,unsigned int maxlen,
284 if (!cptr) return -EINVAL;
285 if (!cptr->info->val_to_sym) return -EINVAL;
286 return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
290 /* Convert a symbolic value to a mask/value pair */
291 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
292 const char *buf,unsigned int len,
293 int *maskptr,int *valptr)
295 if (!cptr) return -EINVAL;
296 if (!cptr->info->sym_to_val) return -EINVAL;
297 return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
301 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
303 char *ptr,unsigned int len)
314 for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
319 cnt = scnprintf(ptr,len,"%s%s%s",
322 ((val & sm) ? "+" : "-")),
324 ptr += cnt; len -= cnt; uc += cnt;
333 cnt = scnprintf(ptr,len,"%s0x%lx",
336 ptr += cnt; len -= cnt; uc += cnt;
338 } else if (um & val) {
339 cnt = scnprintf(ptr,len,"%s+0x%lx",
342 ptr += cnt; len -= cnt; uc += cnt;
344 } else if (um & ~val) {
345 cnt = scnprintf(ptr,len,"%s+0x%lx",
348 ptr += cnt; len -= cnt; uc += cnt;
356 static const char *boolNames[] = {
364 static int parse_token(const char *ptr,unsigned int len,
366 const char * const *names, unsigned int namecnt)
374 if (!names) namecnt = 0;
375 for (idx = 0; idx < namecnt; idx++) {
376 if (!names[idx]) continue;
377 slen = strlen(names[idx]);
378 if (slen != len) continue;
379 if (memcmp(names[idx],ptr,slen)) continue;
384 if ((*ptr == '-') || (*ptr == '+')) {
385 negfl = (*ptr == '-');
388 if (len >= sizeof(buf)) return -EINVAL;
391 *valptr = simple_strtol(buf,&p2,0);
392 if (negfl) *valptr = -(*valptr);
393 if (*p2) return -EINVAL;
398 static int parse_mtoken(const char *ptr,unsigned int len,
400 const char **names,int valid_bits)
408 for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
409 if (!(msk & valid_bits)) continue;
411 if (!names[idx]) continue;
412 slen = strlen(names[idx]);
413 if (slen != len) continue;
414 if (memcmp(names[idx],ptr,slen)) continue;
418 if (len >= sizeof(buf)) return -EINVAL;
421 *valptr = simple_strtol(buf,&p2,0);
422 if (*p2) return -EINVAL;
427 static int parse_tlist(const char *ptr,unsigned int len,
428 int *maskptr,int *valptr,
429 const char **names,int valid_bits)
432 int mask,val,kv,mode,ret;
438 while ((cnt < len) &&
440 (ptr[cnt] >= 127))) cnt++;
444 if ((*ptr == '-') || (*ptr == '+')) {
445 mode = (*ptr == '-') ? -1 : 1;
451 if (ptr[cnt] <= 32) break;
452 if (ptr[cnt] >= 127) break;
456 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
485 /* Convert a symbolic value to a mask/value pair */
486 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
487 const char *ptr,unsigned int len,
488 int *maskptr,int *valptr)
497 while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
498 len -= cnt; ptr += cnt;
500 while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
501 (ptr[len-(cnt+1)] >= 127))) cnt++;
504 if (!len) return -EINVAL;
506 LOCK_TAKE(cptr->hdw->big_lock); do {
507 if (cptr->info->type == pvr2_ctl_int) {
508 ret = parse_token(ptr,len,valptr,NULL,0);
510 ret = pvr2_ctrl_range_check(cptr,*valptr);
513 } else if (cptr->info->type == pvr2_ctl_bool) {
514 ret = parse_token(ptr,len,valptr,boolNames,
515 ARRAY_SIZE(boolNames));
517 *valptr = *valptr ? !0 : 0;
518 } else if (ret == 0) {
519 *valptr = (*valptr & 1) ? !0 : 0;
522 } else if (cptr->info->type == pvr2_ctl_enum) {
525 cptr->info->def.type_enum.value_names,
526 cptr->info->def.type_enum.count);
528 ret = pvr2_ctrl_range_check(cptr,*valptr);
531 } else if (cptr->info->type == pvr2_ctl_bitmask) {
533 ptr,len,maskptr,valptr,
534 cptr->info->def.type_bitmask.bit_names,
535 cptr->info->def.type_bitmask.valid_bits);
537 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
542 /* Convert a given mask/val to a symbolic value */
543 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
545 char *buf,unsigned int maxlen,
551 if (cptr->info->type == pvr2_ctl_int) {
552 *len = scnprintf(buf,maxlen,"%d",val);
554 } else if (cptr->info->type == pvr2_ctl_bool) {
555 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
557 } else if (cptr->info->type == pvr2_ctl_enum) {
558 const char * const *names;
559 names = cptr->info->def.type_enum.value_names;
561 (val < cptr->info->def.type_enum.count)) {
571 } else if (cptr->info->type == pvr2_ctl_bitmask) {
572 *len = gen_bitmask_string(
573 val & mask & cptr->info->def.type_bitmask.valid_bits,
575 cptr->info->def.type_bitmask.bit_names,
582 /* Convert a given mask/val to a symbolic value */
583 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
585 char *buf,unsigned int maxlen,
589 LOCK_TAKE(cptr->hdw->big_lock); do {
590 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
592 } while(0); LOCK_GIVE(cptr->hdw->big_lock);