1 /*
2  *
3  *
4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
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  */
16 
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>
22 
23 
24 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
25 {
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;
31 	} else {
32 		int lim;
33 		lim = cptr->info->def.type_int.min_value;
34 		if (cptr->info->get_min_value) {
35 			cptr->info->get_min_value(cptr,&lim);
36 		}
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);
41 		}
42 		if (val > lim) return -ERANGE;
43 	}
44 	return 0;
45 }
46 
47 
48 /* Set the given control. */
49 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
50 {
51 	return pvr2_ctrl_set_mask_value(cptr,~0,val);
52 }
53 
54 
55 /* Set/clear specific bits of the given control. */
56 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
57 {
58 	int ret = 0;
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);
67 				if (ret < 0) break;
68 			} else if (cptr->info->type != pvr2_ctl_bool) {
69 				break;
70 			}
71 			ret = cptr->info->set_value(cptr,mask,val);
72 		} else {
73 			ret = -EPERM;
74 		}
75 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
76 	return ret;
77 }
78 
79 
80 /* Get the current value of the given control. */
81 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
82 {
83 	int ret = 0;
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);
88 	return ret;
89 }
90 
91 
92 /* Retrieve control's type */
93 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
94 {
95 	if (!cptr) return pvr2_ctl_int;
96 	return cptr->info->type;
97 }
98 
99 
100 /* Retrieve control's maximum value (int type) */
101 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
102 {
103 	int ret = 0;
104 	if (!cptr) return 0;
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;
110 		}
111 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
112 	return ret;
113 }
114 
115 
116 /* Retrieve control's minimum value (int type) */
117 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
118 {
119 	int ret = 0;
120 	if (!cptr) return 0;
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;
126 		}
127 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
128 	return ret;
129 }
130 
131 
132 /* Retrieve control's default value (any type) */
133 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
134 {
135 	int ret = 0;
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);
140 		} else {
141 			*valptr = cptr->info->default_value;
142 		}
143 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
144 	return ret;
145 }
146 
147 
148 /* Retrieve control's enumeration count (enum only) */
149 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
150 {
151 	int ret = 0;
152 	if (!cptr) return 0;
153 	LOCK_TAKE(cptr->hdw->big_lock); do {
154 		if (cptr->info->type == pvr2_ctl_enum) {
155 			ret = cptr->info->def.type_enum.count;
156 		}
157 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
158 	return ret;
159 }
160 
161 
162 /* Retrieve control's valid mask bits (bit mask only) */
163 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
164 {
165 	int ret = 0;
166 	if (!cptr) return 0;
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;
170 		}
171 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
172 	return ret;
173 }
174 
175 
176 /* Retrieve the control's name */
177 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
178 {
179 	if (!cptr) return NULL;
180 	return cptr->info->name;
181 }
182 
183 
184 /* Retrieve the control's desc */
185 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
186 {
187 	if (!cptr) return NULL;
188 	return cptr->info->desc;
189 }
190 
191 
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,
195 			  unsigned int *blen)
196 {
197 	int ret = -EINVAL;
198 	if (!cptr) return 0;
199 	*blen = 0;
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) {
205 				if (names[val]) {
206 					*blen = scnprintf(
207 						bptr,bmax,"%s",
208 						names[val]);
209 				} else {
210 					*blen = 0;
211 				}
212 				ret = 0;
213 			}
214 		} else if (cptr->info->type == pvr2_ctl_bitmask) {
215 			const char **names;
216 			unsigned int idx;
217 			int msk;
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) {
221 				if (val & msk) {
222 					*blen = scnprintf(bptr,bmax,"%s",
223 							  names[idx]);
224 					ret = 0;
225 					break;
226 				}
227 			}
228 		}
229 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
230 	return ret;
231 }
232 
233 
234 /* Return V4L ID for this control or zero if none */
235 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
236 {
237 	if (!cptr) return 0;
238 	return cptr->info->v4l_id;
239 }
240 
241 
242 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
243 {
244 	unsigned int flags = 0;
245 
246 	if (cptr->info->get_v4lflags) {
247 		flags = cptr->info->get_v4lflags(cptr);
248 	}
249 
250 	if (cptr->info->set_value) {
251 		flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
252 	} else {
253 		flags |= V4L2_CTRL_FLAG_READ_ONLY;
254 	}
255 
256 	return flags;
257 }
258 
259 
260 /* Return true if control is writable */
261 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
262 {
263 	if (!cptr) return 0;
264 	return cptr->info->set_value != NULL;
265 }
266 
267 
268 /* Return true if control has custom symbolic representation */
269 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
270 {
271 	if (!cptr) return 0;
272 	if (!cptr->info->val_to_sym) return 0;
273 	if (!cptr->info->sym_to_val) return 0;
274 	return !0;
275 }
276 
277 
278 /* Convert a given mask/val to a custom symbolic value */
279 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
280 				  int mask,int val,
281 				  char *buf,unsigned int maxlen,
282 				  unsigned int *len)
283 {
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);
287 }
288 
289 
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)
294 {
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);
298 }
299 
300 
301 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
302 				       const char **names,
303 				       char *ptr,unsigned int len)
304 {
305 	unsigned int idx;
306 	long sm,um;
307 	int spcFl;
308 	unsigned int uc,cnt;
309 	const char *idStr;
310 
311 	spcFl = 0;
312 	uc = 0;
313 	um = 0;
314 	for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
315 		if (sm & msk) {
316 			msk &= ~sm;
317 			idStr = names[idx];
318 			if (idStr) {
319 				cnt = scnprintf(ptr,len,"%s%s%s",
320 						(spcFl ? " " : ""),
321 						(msk_only ? "" :
322 						 ((val & sm) ? "+" : "-")),
323 						idStr);
324 				ptr += cnt; len -= cnt; uc += cnt;
325 				spcFl = !0;
326 			} else {
327 				um |= sm;
328 			}
329 		}
330 	}
331 	if (um) {
332 		if (msk_only) {
333 			cnt = scnprintf(ptr,len,"%s0x%lx",
334 					(spcFl ? " " : ""),
335 					um);
336 			ptr += cnt; len -= cnt; uc += cnt;
337 			spcFl = !0;
338 		} else if (um & val) {
339 			cnt = scnprintf(ptr,len,"%s+0x%lx",
340 					(spcFl ? " " : ""),
341 					um & val);
342 			ptr += cnt; len -= cnt; uc += cnt;
343 			spcFl = !0;
344 		} else if (um & ~val) {
345 			cnt = scnprintf(ptr,len,"%s+0x%lx",
346 					(spcFl ? " " : ""),
347 					um & ~val);
348 			ptr += cnt; len -= cnt; uc += cnt;
349 			spcFl = !0;
350 		}
351 	}
352 	return uc;
353 }
354 
355 
356 static const char *boolNames[] = {
357 	"false",
358 	"true",
359 	"no",
360 	"yes",
361 };
362 
363 
364 static int parse_token(const char *ptr,unsigned int len,
365 		       int *valptr,
366 		       const char * const *names, unsigned int namecnt)
367 {
368 	char buf[33];
369 	unsigned int slen;
370 	unsigned int idx;
371 	int negfl;
372 	char *p2;
373 	*valptr = 0;
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;
380 		*valptr = idx;
381 		return 0;
382 	}
383 	negfl = 0;
384 	if ((*ptr == '-') || (*ptr == '+')) {
385 		negfl = (*ptr == '-');
386 		ptr++; len--;
387 	}
388 	if (len >= sizeof(buf)) return -EINVAL;
389 	memcpy(buf,ptr,len);
390 	buf[len] = 0;
391 	*valptr = simple_strtol(buf,&p2,0);
392 	if (negfl) *valptr = -(*valptr);
393 	if (*p2) return -EINVAL;
394 	return 1;
395 }
396 
397 
398 static int parse_mtoken(const char *ptr,unsigned int len,
399 			int *valptr,
400 			const char **names,int valid_bits)
401 {
402 	char buf[33];
403 	unsigned int slen;
404 	unsigned int idx;
405 	char *p2;
406 	int msk;
407 	*valptr = 0;
408 	for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
409 		if (!(msk & valid_bits)) continue;
410 		valid_bits &= ~msk;
411 		if (!names[idx]) continue;
412 		slen = strlen(names[idx]);
413 		if (slen != len) continue;
414 		if (memcmp(names[idx],ptr,slen)) continue;
415 		*valptr = msk;
416 		return 0;
417 	}
418 	if (len >= sizeof(buf)) return -EINVAL;
419 	memcpy(buf,ptr,len);
420 	buf[len] = 0;
421 	*valptr = simple_strtol(buf,&p2,0);
422 	if (*p2) return -EINVAL;
423 	return 0;
424 }
425 
426 
427 static int parse_tlist(const char *ptr,unsigned int len,
428 		       int *maskptr,int *valptr,
429 		       const char **names,int valid_bits)
430 {
431 	unsigned int cnt;
432 	int mask,val,kv,mode,ret;
433 	mask = 0;
434 	val = 0;
435 	ret = 0;
436 	while (len) {
437 		cnt = 0;
438 		while ((cnt < len) &&
439 		       ((ptr[cnt] <= 32) ||
440 			(ptr[cnt] >= 127))) cnt++;
441 		ptr += cnt;
442 		len -= cnt;
443 		mode = 0;
444 		if ((*ptr == '-') || (*ptr == '+')) {
445 			mode = (*ptr == '-') ? -1 : 1;
446 			ptr++;
447 			len--;
448 		}
449 		cnt = 0;
450 		while (cnt < len) {
451 			if (ptr[cnt] <= 32) break;
452 			if (ptr[cnt] >= 127) break;
453 			cnt++;
454 		}
455 		if (!cnt) break;
456 		if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
457 			ret = -EINVAL;
458 			break;
459 		}
460 		ptr += cnt;
461 		len -= cnt;
462 		switch (mode) {
463 		case 0:
464 			mask = valid_bits;
465 			val |= kv;
466 			break;
467 		case -1:
468 			mask |= kv;
469 			val &= ~kv;
470 			break;
471 		case 1:
472 			mask |= kv;
473 			val |= kv;
474 			break;
475 		default:
476 			break;
477 		}
478 	}
479 	*maskptr = mask;
480 	*valptr = val;
481 	return ret;
482 }
483 
484 
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)
489 {
490 	int ret = -EINVAL;
491 	unsigned int cnt;
492 
493 	*maskptr = 0;
494 	*valptr = 0;
495 
496 	cnt = 0;
497 	while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
498 	len -= cnt; ptr += cnt;
499 	cnt = 0;
500 	while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
501 			       (ptr[len-(cnt+1)] >= 127))) cnt++;
502 	len -= cnt;
503 
504 	if (!len) return -EINVAL;
505 
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);
509 			if (ret >= 0) {
510 				ret = pvr2_ctrl_range_check(cptr,*valptr);
511 			}
512 			*maskptr = ~0;
513 		} else if (cptr->info->type == pvr2_ctl_bool) {
514 			ret = parse_token(ptr,len,valptr,boolNames,
515 					  ARRAY_SIZE(boolNames));
516 			if (ret == 1) {
517 				*valptr = *valptr ? !0 : 0;
518 			} else if (ret == 0) {
519 				*valptr = (*valptr & 1) ? !0 : 0;
520 			}
521 			*maskptr = 1;
522 		} else if (cptr->info->type == pvr2_ctl_enum) {
523 			ret = parse_token(
524 				ptr,len,valptr,
525 				cptr->info->def.type_enum.value_names,
526 				cptr->info->def.type_enum.count);
527 			if (ret >= 0) {
528 				ret = pvr2_ctrl_range_check(cptr,*valptr);
529 			}
530 			*maskptr = ~0;
531 		} else if (cptr->info->type == pvr2_ctl_bitmask) {
532 			ret = parse_tlist(
533 				ptr,len,maskptr,valptr,
534 				cptr->info->def.type_bitmask.bit_names,
535 				cptr->info->def.type_bitmask.valid_bits);
536 		}
537 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
538 	return ret;
539 }
540 
541 
542 /* Convert a given mask/val to a symbolic value */
543 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
544 				    int mask,int val,
545 				    char *buf,unsigned int maxlen,
546 				    unsigned int *len)
547 {
548 	int ret = -EINVAL;
549 
550 	*len = 0;
551 	if (cptr->info->type == pvr2_ctl_int) {
552 		*len = scnprintf(buf,maxlen,"%d",val);
553 		ret = 0;
554 	} else if (cptr->info->type == pvr2_ctl_bool) {
555 		*len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
556 		ret = 0;
557 	} else if (cptr->info->type == pvr2_ctl_enum) {
558 		const char * const *names;
559 		names = cptr->info->def.type_enum.value_names;
560 		if ((val >= 0) &&
561 		    (val < cptr->info->def.type_enum.count)) {
562 			if (names[val]) {
563 				*len = scnprintf(
564 					buf,maxlen,"%s",
565 					names[val]);
566 			} else {
567 				*len = 0;
568 			}
569 			ret = 0;
570 		}
571 	} else if (cptr->info->type == pvr2_ctl_bitmask) {
572 		*len = gen_bitmask_string(
573 			val & mask & cptr->info->def.type_bitmask.valid_bits,
574 			~0,!0,
575 			cptr->info->def.type_bitmask.bit_names,
576 			buf,maxlen);
577 	}
578 	return ret;
579 }
580 
581 
582 /* Convert a given mask/val to a symbolic value */
583 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
584 			   int mask,int val,
585 			   char *buf,unsigned int maxlen,
586 			   unsigned int *len)
587 {
588 	int ret;
589 	LOCK_TAKE(cptr->hdw->big_lock); do {
590 		ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
591 						      buf,maxlen,len);
592 	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
593 	return ret;
594 }
595