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