• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/src/linux/linux-2.6/drivers/media/video/pvrusb2/
1/*
2 *
3 *  $Id: pvrusb2-ctrl.c,v 1.1.1.1 2007/08/03 18:52:41 Exp $
4 *
5 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 *
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
10 *
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.
15 *
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
19 *
20 */
21
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>
27
28
29static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
30{
31	if (cptr->info->check_value) {
32		if (!cptr->info->check_value(cptr,val)) return -ERANGE;
33	} else {
34		int lim;
35		lim = cptr->info->def.type_int.min_value;
36		if (cptr->info->get_min_value) {
37			cptr->info->get_min_value(cptr,&lim);
38		}
39		if (val < lim) return -ERANGE;
40		lim = cptr->info->def.type_int.max_value;
41		if (cptr->info->get_max_value) {
42			cptr->info->get_max_value(cptr,&lim);
43		}
44		if (val > lim) return -ERANGE;
45	}
46	return 0;
47}
48
49
50/* Set the given control. */
51int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
52{
53	return pvr2_ctrl_set_mask_value(cptr,~0,val);
54}
55
56
57/* Set/clear specific bits of the given control. */
58int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
59{
60	int ret = 0;
61	if (!cptr) return -EINVAL;
62	LOCK_TAKE(cptr->hdw->big_lock); do {
63		if (cptr->info->set_value != 0) {
64			if (cptr->info->type == pvr2_ctl_bitmask) {
65				mask &= cptr->info->def.type_bitmask.valid_bits;
66			} else if (cptr->info->type == pvr2_ctl_int) {
67				ret = pvr2_ctrl_range_check(cptr,val);
68				if (ret < 0) break;
69			} else if (cptr->info->type == pvr2_ctl_enum) {
70				if (val >= cptr->info->def.type_enum.count) {
71					break;
72				}
73			} else if (cptr->info->type != pvr2_ctl_bool) {
74				break;
75			}
76			ret = cptr->info->set_value(cptr,mask,val);
77		} else {
78			ret = -EPERM;
79		}
80	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
81	return ret;
82}
83
84
85/* Get the current value of the given control. */
86int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
87{
88	int ret = 0;
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);
93	return ret;
94}
95
96
97/* Retrieve control's type */
98enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
99{
100	if (!cptr) return pvr2_ctl_int;
101	return cptr->info->type;
102}
103
104
105/* Retrieve control's maximum value (int type) */
106int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
107{
108	int ret = 0;
109	if (!cptr) return 0;
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;
115		}
116	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
117	return ret;
118}
119
120
121/* Retrieve control's minimum value (int type) */
122int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
123{
124	int ret = 0;
125	if (!cptr) return 0;
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;
131		}
132	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
133	return ret;
134}
135
136
137/* Retrieve control's default value (any type) */
138int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
139{
140	int ret = 0;
141	if (!cptr) return 0;
142	LOCK_TAKE(cptr->hdw->big_lock); do {
143		if (cptr->info->type == pvr2_ctl_int) {
144			ret = cptr->info->default_value;
145		}
146	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
147	return ret;
148}
149
150
151/* Retrieve control's enumeration count (enum only) */
152int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
153{
154	int ret = 0;
155	if (!cptr) return 0;
156	LOCK_TAKE(cptr->hdw->big_lock); do {
157		if (cptr->info->type == pvr2_ctl_enum) {
158			ret = cptr->info->def.type_enum.count;
159		}
160	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
161	return ret;
162}
163
164
165/* Retrieve control's valid mask bits (bit mask only) */
166int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
167{
168	int ret = 0;
169	if (!cptr) return 0;
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;
173		}
174	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
175	return ret;
176}
177
178
179/* Retrieve the control's name */
180const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
181{
182	if (!cptr) return NULL;
183	return cptr->info->name;
184}
185
186
187/* Retrieve the control's desc */
188const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
189{
190	if (!cptr) return NULL;
191	return cptr->info->desc;
192}
193
194
195/* Retrieve a control enumeration or bit mask value */
196int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
197			  char *bptr,unsigned int bmax,
198			  unsigned int *blen)
199{
200	int ret = -EINVAL;
201	if (!cptr) return 0;
202	*blen = 0;
203	LOCK_TAKE(cptr->hdw->big_lock); do {
204		if (cptr->info->type == pvr2_ctl_enum) {
205			const char **names;
206			names = cptr->info->def.type_enum.value_names;
207			if ((val >= 0) &&
208			    (val < cptr->info->def.type_enum.count)) {
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 */
239int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
240{
241	if (!cptr) return 0;
242	return cptr->info->v4l_id;
243}
244
245
246unsigned 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 */
265int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
266{
267	if (!cptr) return 0;
268	return cptr->info->set_value != 0;
269}
270
271
272/* Return true if control has custom symbolic representation */
273int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
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 */
283int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
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 */
295int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
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
305static 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
360static const char *boolNames[] = {
361	"false",
362	"true",
363	"no",
364	"yes",
365};
366
367
368static int parse_token(const char *ptr,unsigned int len,
369		       int *valptr,
370		       const char **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
402static 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
431static 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 */
490int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
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			if (maskptr) *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			if (maskptr) *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			    ((*valptr < 0) ||
533			     (*valptr >= cptr->info->def.type_enum.count))) {
534				ret = -ERANGE;
535			}
536			if (maskptr) *maskptr = ~0;
537		} else if (cptr->info->type == pvr2_ctl_bitmask) {
538			ret = parse_tlist(
539				ptr,len,maskptr,valptr,
540				cptr->info->def.type_bitmask.bit_names,
541				cptr->info->def.type_bitmask.valid_bits);
542		}
543	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
544	return ret;
545}
546
547
548/* Convert a given mask/val to a symbolic value */
549int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
550				    int mask,int val,
551				    char *buf,unsigned int maxlen,
552				    unsigned int *len)
553{
554	int ret = -EINVAL;
555
556	*len = 0;
557	if (cptr->info->type == pvr2_ctl_int) {
558		*len = scnprintf(buf,maxlen,"%d",val);
559		ret = 0;
560	} else if (cptr->info->type == pvr2_ctl_bool) {
561		*len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
562		ret = 0;
563	} else if (cptr->info->type == pvr2_ctl_enum) {
564		const char **names;
565		names = cptr->info->def.type_enum.value_names;
566		if ((val >= 0) &&
567		    (val < cptr->info->def.type_enum.count)) {
568			if (names[val]) {
569				*len = scnprintf(
570					buf,maxlen,"%s",
571					names[val]);
572			} else {
573				*len = 0;
574			}
575			ret = 0;
576		}
577	} else if (cptr->info->type == pvr2_ctl_bitmask) {
578		*len = gen_bitmask_string(
579			val & mask & cptr->info->def.type_bitmask.valid_bits,
580			~0,!0,
581			cptr->info->def.type_bitmask.bit_names,
582			buf,maxlen);
583	}
584	return ret;
585}
586
587
588/* Convert a given mask/val to a symbolic value */
589int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
590			   int mask,int val,
591			   char *buf,unsigned int maxlen,
592			   unsigned int *len)
593{
594	int ret;
595	LOCK_TAKE(cptr->hdw->big_lock); do {
596		ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
597						      buf,maxlen,len);
598	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
599	return ret;
600}
601
602
603/*
604  Stuff for Emacs to see, in order to encourage consistent editing style:
605  *** Local Variables: ***
606  *** mode: c ***
607  *** fill-column: 75 ***
608  *** tab-width: 8 ***
609  *** c-basic-offset: 8 ***
610  *** End: ***
611  */
612