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