aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-ctrl.c')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.c544
1 files changed, 544 insertions, 0 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
new file mode 100644
index 000000000000..3577d5bfa007
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -0,0 +1,544 @@
1/*
2 *
3 * $Id$
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
29/* Set the given control. */
30int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
31{
32 return pvr2_ctrl_set_mask_value(cptr,~0,val);
33}
34
35
36/* Set/clear specific bits of the given control. */
37int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
38{
39 int ret = 0;
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) {
47 break;
48 }
49 if (val > cptr->info->def.type_int.max_value) {
50 break;
51 }
52 } else if (cptr->info->type == pvr2_ctl_enum) {
53 if (val >= cptr->info->def.type_enum.count) {
54 break;
55 }
56 }
57 ret = cptr->info->set_value(cptr,mask,val);
58 } else {
59 ret = -EPERM;
60 }
61 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
62 return ret;
63}
64
65
66/* Get the current value of the given control. */
67int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
68{
69 int ret = 0;
70 if (!cptr) return -EINVAL;
71 LOCK_TAKE(cptr->hdw->big_lock); do {
72 ret = cptr->info->get_value(cptr,valptr);
73 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
74 return ret;
75}
76
77
78/* Retrieve control's type */
79enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
80{
81 if (!cptr) return pvr2_ctl_int;
82 return cptr->info->type;
83}
84
85
86/* Retrieve control's maximum value (int type) */
87int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
88{
89 int ret = 0;
90 if (!cptr) return 0;
91 LOCK_TAKE(cptr->hdw->big_lock); do {
92 if (cptr->info->type == pvr2_ctl_int) {
93 ret = cptr->info->def.type_int.max_value;
94 }
95 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
96 return ret;
97}
98
99
100/* Retrieve control's minimum value (int type) */
101int pvr2_ctrl_get_min(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->type == pvr2_ctl_int) {
107 ret = cptr->info->def.type_int.min_value;
108 }
109 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
110 return ret;
111}
112
113
114/* Retrieve control's default value (any type) */
115int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
116{
117 int ret = 0;
118 if (!cptr) return 0;
119 LOCK_TAKE(cptr->hdw->big_lock); do {
120 if (cptr->info->type == pvr2_ctl_int) {
121 ret = cptr->info->default_value;
122 }
123 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
124 return ret;
125}
126
127
128/* Retrieve control's enumeration count (enum only) */
129int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
130{
131 int ret = 0;
132 if (!cptr) return 0;
133 LOCK_TAKE(cptr->hdw->big_lock); do {
134 if (cptr->info->type == pvr2_ctl_enum) {
135 ret = cptr->info->def.type_enum.count;
136 }
137 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
138 return ret;
139}
140
141
142/* Retrieve control's valid mask bits (bit mask only) */
143int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
144{
145 int ret = 0;
146 if (!cptr) return 0;
147 LOCK_TAKE(cptr->hdw->big_lock); do {
148 if (cptr->info->type == pvr2_ctl_bitmask) {
149 ret = cptr->info->def.type_bitmask.valid_bits;
150 }
151 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
152 return ret;
153}
154
155
156/* Retrieve the control's name */
157const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
158{
159 if (!cptr) return 0;
160 return cptr->info->name;
161}
162
163
164/* Retrieve the control's desc */
165const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
166{
167 if (!cptr) return 0;
168 return cptr->info->desc;
169}
170
171
172/* Retrieve a control enumeration or bit mask value */
173int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
174 char *bptr,unsigned int bmax,
175 unsigned int *blen)
176{
177 int ret = -EINVAL;
178 if (!cptr) return 0;
179 *blen = 0;
180 LOCK_TAKE(cptr->hdw->big_lock); do {
181 if (cptr->info->type == pvr2_ctl_enum) {
182 const char **names;
183 names = cptr->info->def.type_enum.value_names;
184 if ((val >= 0) &&
185 (val < cptr->info->def.type_enum.count)) {
186 if (names[val]) {
187 *blen = scnprintf(
188 bptr,bmax,"%s",
189 names[val]);
190 } else {
191 *blen = 0;
192 }
193 ret = 0;
194 }
195 } else if (cptr->info->type == pvr2_ctl_bitmask) {
196 const char **names;
197 unsigned int idx;
198 int msk;
199 names = cptr->info->def.type_bitmask.bit_names;
200 val &= cptr->info->def.type_bitmask.valid_bits;
201 for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
202 if (val & msk) {
203 *blen = scnprintf(bptr,bmax,"%s",
204 names[idx]);
205 ret = 0;
206 break;
207 }
208 }
209 }
210 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
211 return ret;
212}
213
214
215/* Return true if control is writable */
216int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
217{
218 if (!cptr) return 0;
219 return cptr->info->set_value != 0;
220}
221
222
223/* Return true if control has custom symbolic representation */
224int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
225{
226 if (!cptr) return 0;
227 if (!cptr->info->val_to_sym) return 0;
228 if (!cptr->info->sym_to_val) return 0;
229 return !0;
230}
231
232
233/* Convert a given mask/val to a custom symbolic value */
234int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
235 int mask,int val,
236 char *buf,unsigned int maxlen,
237 unsigned int *len)
238{
239 if (!cptr) return -EINVAL;
240 if (!cptr->info->val_to_sym) return -EINVAL;
241 return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
242}
243
244
245/* Convert a symbolic value to a mask/value pair */
246int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
247 const char *buf,unsigned int len,
248 int *maskptr,int *valptr)
249{
250 if (!cptr) return -EINVAL;
251 if (!cptr->info->sym_to_val) return -EINVAL;
252 return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
253}
254
255
256static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
257 const char **names,
258 char *ptr,unsigned int len)
259{
260 unsigned int idx;
261 long sm,um;
262 int spcFl;
263 unsigned int uc,cnt;
264 const char *idStr;
265
266 spcFl = 0;
267 uc = 0;
268 um = 0;
269 for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
270 if (sm & msk) {
271 msk &= ~sm;
272 idStr = names[idx];
273 if (idStr) {
274 cnt = scnprintf(ptr,len,"%s%s%s",
275 (spcFl ? " " : ""),
276 (msk_only ? "" :
277 ((val & sm) ? "+" : "-")),
278 idStr);
279 ptr += cnt; len -= cnt; uc += cnt;
280 spcFl = !0;
281 } else {
282 um |= sm;
283 }
284 }
285 }
286 if (um) {
287 if (msk_only) {
288 cnt = scnprintf(ptr,len,"%s0x%lx",
289 (spcFl ? " " : ""),
290 um);
291 ptr += cnt; len -= cnt; uc += cnt;
292 spcFl = !0;
293 } else if (um & val) {
294 cnt = scnprintf(ptr,len,"%s+0x%lx",
295 (spcFl ? " " : ""),
296 um & val);
297 ptr += cnt; len -= cnt; uc += cnt;
298 spcFl = !0;
299 } else if (um & ~val) {
300 cnt = scnprintf(ptr,len,"%s+0x%lx",
301 (spcFl ? " " : ""),
302 um & ~val);
303 ptr += cnt; len -= cnt; uc += cnt;
304 spcFl = !0;
305 }
306 }
307 return uc;
308}
309
310
311static int parse_token(const char *ptr,unsigned int len,
312 int *valptr,
313 const char **names,unsigned int namecnt)
314{
315 char buf[33];
316 unsigned int slen;
317 unsigned int idx;
318 int negfl;
319 char *p2;
320 *valptr = 0;
321 if (!names) namecnt = 0;
322 for (idx = 0; idx < namecnt; idx++) {
323 if (!names[idx]) continue;
324 slen = strlen(names[idx]);
325 if (slen != len) continue;
326 if (memcmp(names[idx],ptr,slen)) continue;
327 *valptr = idx;
328 return 0;
329 }
330 negfl = 0;
331 if ((*ptr == '-') || (*ptr == '+')) {
332 negfl = (*ptr == '-');
333 ptr++; len--;
334 }
335 if (len >= sizeof(buf)) return -EINVAL;
336 memcpy(buf,ptr,len);
337 buf[len] = 0;
338 *valptr = simple_strtol(buf,&p2,0);
339 if (negfl) *valptr = -(*valptr);
340 if (*p2) return -EINVAL;
341 return 0;
342}
343
344
345static int parse_mtoken(const char *ptr,unsigned int len,
346 int *valptr,
347 const char **names,int valid_bits)
348{
349 char buf[33];
350 unsigned int slen;
351 unsigned int idx;
352 char *p2;
353 int msk;
354 *valptr = 0;
355 for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
356 if (!msk & valid_bits) continue;
357 valid_bits &= ~msk;
358 if (!names[idx]) continue;
359 slen = strlen(names[idx]);
360 if (slen != len) continue;
361 if (memcmp(names[idx],ptr,slen)) continue;
362 *valptr = msk;
363 return 0;
364 }
365 if (len >= sizeof(buf)) return -EINVAL;
366 memcpy(buf,ptr,len);
367 buf[len] = 0;
368 *valptr = simple_strtol(buf,&p2,0);
369 if (*p2) return -EINVAL;
370 return 0;
371}
372
373
374static int parse_tlist(const char *ptr,unsigned int len,
375 int *maskptr,int *valptr,
376 const char **names,int valid_bits)
377{
378 unsigned int cnt;
379 int mask,val,kv,mode,ret;
380 mask = 0;
381 val = 0;
382 ret = 0;
383 while (len) {
384 cnt = 0;
385 while ((cnt < len) &&
386 ((ptr[cnt] <= 32) ||
387 (ptr[cnt] >= 127))) cnt++;
388 ptr += cnt;
389 len -= cnt;
390 mode = 0;
391 if ((*ptr == '-') || (*ptr == '+')) {
392 mode = (*ptr == '-') ? -1 : 1;
393 ptr++;
394 len--;
395 }
396 cnt = 0;
397 while (cnt < len) {
398 if (ptr[cnt] <= 32) break;
399 if (ptr[cnt] >= 127) break;
400 cnt++;
401 }
402 if (!cnt) break;
403 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
404 ret = -EINVAL;
405 break;
406 }
407 ptr += cnt;
408 len -= cnt;
409 switch (mode) {
410 case 0:
411 mask = valid_bits;
412 val |= kv;
413 break;
414 case -1:
415 mask |= kv;
416 val &= ~kv;
417 break;
418 case 1:
419 mask |= kv;
420 val |= kv;
421 break;
422 default:
423 break;
424 }
425 }
426 *maskptr = mask;
427 *valptr = val;
428 return ret;
429}
430
431
432/* Convert a symbolic value to a mask/value pair */
433int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
434 const char *ptr,unsigned int len,
435 int *maskptr,int *valptr)
436{
437 int ret = -EINVAL;
438 unsigned int cnt;
439
440 *maskptr = 0;
441 *valptr = 0;
442
443 cnt = 0;
444 while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
445 len -= cnt; ptr += cnt;
446 cnt = 0;
447 while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
448 (ptr[len-(cnt+1)] >= 127))) cnt++;
449 len -= cnt;
450
451 if (!len) return -EINVAL;
452
453 LOCK_TAKE(cptr->hdw->big_lock); do {
454 if (cptr->info->type == pvr2_ctl_int) {
455 ret = parse_token(ptr,len,valptr,0,0);
456 if ((ret == 0) &&
457 ((*valptr < cptr->info->def.type_int.min_value) ||
458 (*valptr > cptr->info->def.type_int.max_value))) {
459 ret = -EINVAL;
460 }
461 if (maskptr) *maskptr = ~0;
462 } else if (cptr->info->type == pvr2_ctl_enum) {
463 ret = parse_token(
464 ptr,len,valptr,
465 cptr->info->def.type_enum.value_names,
466 cptr->info->def.type_enum.count);
467 if ((ret == 0) &&
468 ((*valptr < 0) ||
469 (*valptr >= cptr->info->def.type_enum.count))) {
470 ret = -EINVAL;
471 }
472 if (maskptr) *maskptr = ~0;
473 } else if (cptr->info->type == pvr2_ctl_bitmask) {
474 ret = parse_tlist(
475 ptr,len,maskptr,valptr,
476 cptr->info->def.type_bitmask.bit_names,
477 cptr->info->def.type_bitmask.valid_bits);
478 }
479 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
480 return ret;
481}
482
483
484/* Convert a given mask/val to a symbolic value */
485int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
486 int mask,int val,
487 char *buf,unsigned int maxlen,
488 unsigned int *len)
489{
490 int ret = -EINVAL;
491
492 *len = 0;
493 if (cptr->info->type == pvr2_ctl_int) {
494 *len = scnprintf(buf,maxlen,"%d",val);
495 ret = 0;
496 } else if (cptr->info->type == pvr2_ctl_enum) {
497 const char **names;
498 names = cptr->info->def.type_enum.value_names;
499 if ((val >= 0) &&
500 (val < cptr->info->def.type_enum.count)) {
501 if (names[val]) {
502 *len = scnprintf(
503 buf,maxlen,"%s",
504 names[val]);
505 } else {
506 *len = 0;
507 }
508 ret = 0;
509 }
510 } else if (cptr->info->type == pvr2_ctl_bitmask) {
511 *len = gen_bitmask_string(
512 val & mask & cptr->info->def.type_bitmask.valid_bits,
513 ~0,!0,
514 cptr->info->def.type_bitmask.bit_names,
515 buf,maxlen);
516 }
517 return ret;
518}
519
520
521/* Convert a given mask/val to a symbolic value */
522int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
523 int mask,int val,
524 char *buf,unsigned int maxlen,
525 unsigned int *len)
526{
527 int ret;
528 LOCK_TAKE(cptr->hdw->big_lock); do {
529 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
530 buf,maxlen,len);
531 } while(0); LOCK_GIVE(cptr->hdw->big_lock);
532 return ret;
533}
534
535
536/*
537 Stuff for Emacs to see, in order to encourage consistent editing style:
538 *** Local Variables: ***
539 *** mode: c ***
540 *** fill-column: 75 ***
541 *** tab-width: 8 ***
542 *** c-basic-offset: 8 ***
543 *** End: ***
544 */