Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pvrusb2-ctrl.c
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Copyright (C) 2005 Mike Isely <[email protected]>
5  *
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
9  *
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.
14  *
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
18  *
19  */
20 
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>
26 
27 
28 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
29 {
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;
35  } else {
36  int lim;
37  lim = cptr->info->def.type_int.min_value;
38  if (cptr->info->get_min_value) {
39  cptr->info->get_min_value(cptr,&lim);
40  }
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);
45  }
46  if (val > lim) return -ERANGE;
47  }
48  return 0;
49 }
50 
51 
52 /* Set the given control. */
53 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
54 {
55  return pvr2_ctrl_set_mask_value(cptr,~0,val);
56 }
57 
58 
59 /* Set/clear specific bits of the given control. */
60 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
61 {
62  int ret = 0;
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);
71  if (ret < 0) break;
72  } else if (cptr->info->type != pvr2_ctl_bool) {
73  break;
74  }
75  ret = cptr->info->set_value(cptr,mask,val);
76  } else {
77  ret = -EPERM;
78  }
79  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
80  return ret;
81 }
82 
83 
84 /* Get the current value of the given control. */
85 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
86 {
87  int ret = 0;
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);
92  return ret;
93 }
94 
95 
96 /* Retrieve control's type */
98 {
99  if (!cptr) return pvr2_ctl_int;
100  return cptr->info->type;
101 }
102 
103 
104 /* Retrieve control's maximum value (int type) */
105 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
106 {
107  int ret = 0;
108  if (!cptr) return 0;
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;
114  }
115  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
116  return ret;
117 }
118 
119 
120 /* Retrieve control's minimum value (int type) */
121 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
122 {
123  int ret = 0;
124  if (!cptr) return 0;
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;
130  }
131  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
132  return ret;
133 }
134 
135 
136 /* Retrieve control's default value (any type) */
137 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
138 {
139  int ret = 0;
140  if (!cptr) return -EINVAL;
141  LOCK_TAKE(cptr->hdw->big_lock); do {
142  if (cptr->info->get_def_value) {
143  ret = cptr->info->get_def_value(cptr, valptr);
144  } else {
145  *valptr = cptr->info->default_value;
146  }
147  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
148  return ret;
149 }
150 
151 
152 /* Retrieve control's enumeration count (enum only) */
153 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
154 {
155  int ret = 0;
156  if (!cptr) return 0;
157  LOCK_TAKE(cptr->hdw->big_lock); do {
158  if (cptr->info->type == pvr2_ctl_enum) {
159  ret = cptr->info->def.type_enum.count;
160  }
161  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
162  return ret;
163 }
164 
165 
166 /* Retrieve control's valid mask bits (bit mask only) */
167 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
168 {
169  int ret = 0;
170  if (!cptr) return 0;
171  LOCK_TAKE(cptr->hdw->big_lock); do {
172  if (cptr->info->type == pvr2_ctl_bitmask) {
173  ret = cptr->info->def.type_bitmask.valid_bits;
174  }
175  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
176  return ret;
177 }
178 
179 
180 /* Retrieve the control's name */
181 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
182 {
183  if (!cptr) return NULL;
184  return cptr->info->name;
185 }
186 
187 
188 /* Retrieve the control's desc */
189 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
190 {
191  if (!cptr) return NULL;
192  return cptr->info->desc;
193 }
194 
195 
196 /* Retrieve a control enumeration or bit mask value */
197 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
198  char *bptr,unsigned int bmax,
199  unsigned int *blen)
200 {
201  int ret = -EINVAL;
202  if (!cptr) return 0;
203  *blen = 0;
204  LOCK_TAKE(cptr->hdw->big_lock); do {
205  if (cptr->info->type == pvr2_ctl_enum) {
206  const char * const *names;
207  names = cptr->info->def.type_enum.value_names;
208  if (pvr2_ctrl_range_check(cptr,val) == 0) {
209  if (names[val]) {
210  *blen = scnprintf(
211  bptr,bmax,"%s",
212  names[val]);
213  } else {
214  *blen = 0;
215  }
216  ret = 0;
217  }
218  } else if (cptr->info->type == pvr2_ctl_bitmask) {
219  const char **names;
220  unsigned int idx;
221  int msk;
222  names = cptr->info->def.type_bitmask.bit_names;
223  val &= cptr->info->def.type_bitmask.valid_bits;
224  for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
225  if (val & msk) {
226  *blen = scnprintf(bptr,bmax,"%s",
227  names[idx]);
228  ret = 0;
229  break;
230  }
231  }
232  }
233  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
234  return ret;
235 }
236 
237 
238 /* Return V4L ID for this control or zero if none */
240 {
241  if (!cptr) return 0;
242  return cptr->info->v4l_id;
243 }
244 
245 
246 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
247 {
248  unsigned int flags = 0;
249 
250  if (cptr->info->get_v4lflags) {
251  flags = cptr->info->get_v4lflags(cptr);
252  }
253 
254  if (cptr->info->set_value) {
255  flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
256  } else {
257  flags |= V4L2_CTRL_FLAG_READ_ONLY;
258  }
259 
260  return flags;
261 }
262 
263 
264 /* Return true if control is writable */
266 {
267  if (!cptr) return 0;
268  return cptr->info->set_value != NULL;
269 }
270 
271 
272 /* Return true if control has custom symbolic representation */
274 {
275  if (!cptr) return 0;
276  if (!cptr->info->val_to_sym) return 0;
277  if (!cptr->info->sym_to_val) return 0;
278  return !0;
279 }
280 
281 
282 /* Convert a given mask/val to a custom symbolic value */
284  int mask,int val,
285  char *buf,unsigned int maxlen,
286  unsigned int *len)
287 {
288  if (!cptr) return -EINVAL;
289  if (!cptr->info->val_to_sym) return -EINVAL;
290  return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
291 }
292 
293 
294 /* Convert a symbolic value to a mask/value pair */
296  const char *buf,unsigned int len,
297  int *maskptr,int *valptr)
298 {
299  if (!cptr) return -EINVAL;
300  if (!cptr->info->sym_to_val) return -EINVAL;
301  return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
302 }
303 
304 
305 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
306  const char **names,
307  char *ptr,unsigned int len)
308 {
309  unsigned int idx;
310  long sm,um;
311  int spcFl;
312  unsigned int uc,cnt;
313  const char *idStr;
314 
315  spcFl = 0;
316  uc = 0;
317  um = 0;
318  for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
319  if (sm & msk) {
320  msk &= ~sm;
321  idStr = names[idx];
322  if (idStr) {
323  cnt = scnprintf(ptr,len,"%s%s%s",
324  (spcFl ? " " : ""),
325  (msk_only ? "" :
326  ((val & sm) ? "+" : "-")),
327  idStr);
328  ptr += cnt; len -= cnt; uc += cnt;
329  spcFl = !0;
330  } else {
331  um |= sm;
332  }
333  }
334  }
335  if (um) {
336  if (msk_only) {
337  cnt = scnprintf(ptr,len,"%s0x%lx",
338  (spcFl ? " " : ""),
339  um);
340  ptr += cnt; len -= cnt; uc += cnt;
341  spcFl = !0;
342  } else if (um & val) {
343  cnt = scnprintf(ptr,len,"%s+0x%lx",
344  (spcFl ? " " : ""),
345  um & val);
346  ptr += cnt; len -= cnt; uc += cnt;
347  spcFl = !0;
348  } else if (um & ~val) {
349  cnt = scnprintf(ptr,len,"%s+0x%lx",
350  (spcFl ? " " : ""),
351  um & ~val);
352  ptr += cnt; len -= cnt; uc += cnt;
353  spcFl = !0;
354  }
355  }
356  return uc;
357 }
358 
359 
360 static const char *boolNames[] = {
361  "false",
362  "true",
363  "no",
364  "yes",
365 };
366 
367 
368 static int parse_token(const char *ptr,unsigned int len,
369  int *valptr,
370  const char * const *names, unsigned int namecnt)
371 {
372  char buf[33];
373  unsigned int slen;
374  unsigned int idx;
375  int negfl;
376  char *p2;
377  *valptr = 0;
378  if (!names) namecnt = 0;
379  for (idx = 0; idx < namecnt; idx++) {
380  if (!names[idx]) continue;
381  slen = strlen(names[idx]);
382  if (slen != len) continue;
383  if (memcmp(names[idx],ptr,slen)) continue;
384  *valptr = idx;
385  return 0;
386  }
387  negfl = 0;
388  if ((*ptr == '-') || (*ptr == '+')) {
389  negfl = (*ptr == '-');
390  ptr++; len--;
391  }
392  if (len >= sizeof(buf)) return -EINVAL;
393  memcpy(buf,ptr,len);
394  buf[len] = 0;
395  *valptr = simple_strtol(buf,&p2,0);
396  if (negfl) *valptr = -(*valptr);
397  if (*p2) return -EINVAL;
398  return 1;
399 }
400 
401 
402 static int parse_mtoken(const char *ptr,unsigned int len,
403  int *valptr,
404  const char **names,int valid_bits)
405 {
406  char buf[33];
407  unsigned int slen;
408  unsigned int idx;
409  char *p2;
410  int msk;
411  *valptr = 0;
412  for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
413  if (!(msk & valid_bits)) continue;
414  valid_bits &= ~msk;
415  if (!names[idx]) continue;
416  slen = strlen(names[idx]);
417  if (slen != len) continue;
418  if (memcmp(names[idx],ptr,slen)) continue;
419  *valptr = msk;
420  return 0;
421  }
422  if (len >= sizeof(buf)) return -EINVAL;
423  memcpy(buf,ptr,len);
424  buf[len] = 0;
425  *valptr = simple_strtol(buf,&p2,0);
426  if (*p2) return -EINVAL;
427  return 0;
428 }
429 
430 
431 static int parse_tlist(const char *ptr,unsigned int len,
432  int *maskptr,int *valptr,
433  const char **names,int valid_bits)
434 {
435  unsigned int cnt;
436  int mask,val,kv,mode,ret;
437  mask = 0;
438  val = 0;
439  ret = 0;
440  while (len) {
441  cnt = 0;
442  while ((cnt < len) &&
443  ((ptr[cnt] <= 32) ||
444  (ptr[cnt] >= 127))) cnt++;
445  ptr += cnt;
446  len -= cnt;
447  mode = 0;
448  if ((*ptr == '-') || (*ptr == '+')) {
449  mode = (*ptr == '-') ? -1 : 1;
450  ptr++;
451  len--;
452  }
453  cnt = 0;
454  while (cnt < len) {
455  if (ptr[cnt] <= 32) break;
456  if (ptr[cnt] >= 127) break;
457  cnt++;
458  }
459  if (!cnt) break;
460  if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
461  ret = -EINVAL;
462  break;
463  }
464  ptr += cnt;
465  len -= cnt;
466  switch (mode) {
467  case 0:
468  mask = valid_bits;
469  val |= kv;
470  break;
471  case -1:
472  mask |= kv;
473  val &= ~kv;
474  break;
475  case 1:
476  mask |= kv;
477  val |= kv;
478  break;
479  default:
480  break;
481  }
482  }
483  *maskptr = mask;
484  *valptr = val;
485  return ret;
486 }
487 
488 
489 /* Convert a symbolic value to a mask/value pair */
491  const char *ptr,unsigned int len,
492  int *maskptr,int *valptr)
493 {
494  int ret = -EINVAL;
495  unsigned int cnt;
496 
497  *maskptr = 0;
498  *valptr = 0;
499 
500  cnt = 0;
501  while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
502  len -= cnt; ptr += cnt;
503  cnt = 0;
504  while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
505  (ptr[len-(cnt+1)] >= 127))) cnt++;
506  len -= cnt;
507 
508  if (!len) return -EINVAL;
509 
510  LOCK_TAKE(cptr->hdw->big_lock); do {
511  if (cptr->info->type == pvr2_ctl_int) {
512  ret = parse_token(ptr,len,valptr,NULL,0);
513  if (ret >= 0) {
514  ret = pvr2_ctrl_range_check(cptr,*valptr);
515  }
516  *maskptr = ~0;
517  } else if (cptr->info->type == pvr2_ctl_bool) {
518  ret = parse_token(ptr,len,valptr,boolNames,
519  ARRAY_SIZE(boolNames));
520  if (ret == 1) {
521  *valptr = *valptr ? !0 : 0;
522  } else if (ret == 0) {
523  *valptr = (*valptr & 1) ? !0 : 0;
524  }
525  *maskptr = 1;
526  } else if (cptr->info->type == pvr2_ctl_enum) {
527  ret = parse_token(
528  ptr,len,valptr,
529  cptr->info->def.type_enum.value_names,
530  cptr->info->def.type_enum.count);
531  if (ret >= 0) {
532  ret = pvr2_ctrl_range_check(cptr,*valptr);
533  }
534  *maskptr = ~0;
535  } else if (cptr->info->type == pvr2_ctl_bitmask) {
536  ret = parse_tlist(
537  ptr,len,maskptr,valptr,
538  cptr->info->def.type_bitmask.bit_names,
539  cptr->info->def.type_bitmask.valid_bits);
540  }
541  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
542  return ret;
543 }
544 
545 
546 /* Convert a given mask/val to a symbolic value */
548  int mask,int val,
549  char *buf,unsigned int maxlen,
550  unsigned int *len)
551 {
552  int ret = -EINVAL;
553 
554  *len = 0;
555  if (cptr->info->type == pvr2_ctl_int) {
556  *len = scnprintf(buf,maxlen,"%d",val);
557  ret = 0;
558  } else if (cptr->info->type == pvr2_ctl_bool) {
559  *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
560  ret = 0;
561  } else if (cptr->info->type == pvr2_ctl_enum) {
562  const char * const *names;
563  names = cptr->info->def.type_enum.value_names;
564  if ((val >= 0) &&
565  (val < cptr->info->def.type_enum.count)) {
566  if (names[val]) {
567  *len = scnprintf(
568  buf,maxlen,"%s",
569  names[val]);
570  } else {
571  *len = 0;
572  }
573  ret = 0;
574  }
575  } else if (cptr->info->type == pvr2_ctl_bitmask) {
576  *len = gen_bitmask_string(
577  val & mask & cptr->info->def.type_bitmask.valid_bits,
578  ~0,!0,
579  cptr->info->def.type_bitmask.bit_names,
580  buf,maxlen);
581  }
582  return ret;
583 }
584 
585 
586 /* Convert a given mask/val to a symbolic value */
588  int mask,int val,
589  char *buf,unsigned int maxlen,
590  unsigned int *len)
591 {
592  int ret;
593  LOCK_TAKE(cptr->hdw->big_lock); do {
594  ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
595  buf,maxlen,len);
596  } while(0); LOCK_GIVE(cptr->hdw->big_lock);
597  return ret;
598 }
599 
600 
601 /*
602  Stuff for Emacs to see, in order to encourage consistent editing style:
603  *** Local Variables: ***
604  *** mode: c ***
605  *** fill-column: 75 ***
606  *** tab-width: 8 ***
607  *** c-basic-offset: 8 ***
608  *** End: ***
609  */