Merge branches 'pxa' and 'orion-fixes1'
[linux-2.6] / drivers / media / video / pvrusb2 / pvrusb2-ctrl.c
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 static 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 if (cptr->info->type == pvr2_ctl_enum) {
34                 if (val < 0) return -ERANGE;
35                 if (val >= cptr->info->def.type_enum.count) return -ERANGE;
36         } else {
37                 int lim;
38                 lim = cptr->info->def.type_int.min_value;
39                 if (cptr->info->get_min_value) {
40                         cptr->info->get_min_value(cptr,&lim);
41                 }
42                 if (val < lim) return -ERANGE;
43                 lim = cptr->info->def.type_int.max_value;
44                 if (cptr->info->get_max_value) {
45                         cptr->info->get_max_value(cptr,&lim);
46                 }
47                 if (val > lim) return -ERANGE;
48         }
49         return 0;
50 }
51
52
53 /* Set the given control. */
54 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
55 {
56         return pvr2_ctrl_set_mask_value(cptr,~0,val);
57 }
58
59
60 /* Set/clear specific bits of the given control. */
61 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
62 {
63         int ret = 0;
64         if (!cptr) return -EINVAL;
65         LOCK_TAKE(cptr->hdw->big_lock); do {
66                 if (cptr->info->set_value) {
67                         if (cptr->info->type == pvr2_ctl_bitmask) {
68                                 mask &= cptr->info->def.type_bitmask.valid_bits;
69                         } else if ((cptr->info->type == pvr2_ctl_int)||
70                                    (cptr->info->type == pvr2_ctl_enum)) {
71                                 ret = pvr2_ctrl_range_check(cptr,val);
72                                 if (ret < 0) break;
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. */
86 int 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 */
98 enum 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) */
106 int 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) */
122 int 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) */
138 int 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) */
152 int 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) */
166 int 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 */
180 const 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 */
188 const 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 */
196 int 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 (pvr2_ctrl_range_check(cptr,val) == 0) {
208                                 if (names[val]) {
209                                         *blen = scnprintf(
210                                                 bptr,bmax,"%s",
211                                                 names[val]);
212                                 } else {
213                                         *blen = 0;
214                                 }
215                                 ret = 0;
216                         }
217                 } else if (cptr->info->type == pvr2_ctl_bitmask) {
218                         const char **names;
219                         unsigned int idx;
220                         int msk;
221                         names = cptr->info->def.type_bitmask.bit_names;
222                         val &= cptr->info->def.type_bitmask.valid_bits;
223                         for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
224                                 if (val & msk) {
225                                         *blen = scnprintf(bptr,bmax,"%s",
226                                                           names[idx]);
227                                         ret = 0;
228                                         break;
229                                 }
230                         }
231                 }
232         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
233         return ret;
234 }
235
236
237 /* Return V4L ID for this control or zero if none */
238 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
239 {
240         if (!cptr) return 0;
241         return cptr->info->v4l_id;
242 }
243
244
245 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
246 {
247         unsigned int flags = 0;
248
249         if (cptr->info->get_v4lflags) {
250                 flags = cptr->info->get_v4lflags(cptr);
251         }
252
253         if (cptr->info->set_value) {
254                 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
255         } else {
256                 flags |= V4L2_CTRL_FLAG_READ_ONLY;
257         }
258
259         return flags;
260 }
261
262
263 /* Return true if control is writable */
264 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
265 {
266         if (!cptr) return 0;
267         return cptr->info->set_value != NULL;
268 }
269
270
271 /* Return true if control has custom symbolic representation */
272 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
273 {
274         if (!cptr) return 0;
275         if (!cptr->info->val_to_sym) return 0;
276         if (!cptr->info->sym_to_val) return 0;
277         return !0;
278 }
279
280
281 /* Convert a given mask/val to a custom symbolic value */
282 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
283                                   int mask,int val,
284                                   char *buf,unsigned int maxlen,
285                                   unsigned int *len)
286 {
287         if (!cptr) return -EINVAL;
288         if (!cptr->info->val_to_sym) return -EINVAL;
289         return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
290 }
291
292
293 /* Convert a symbolic value to a mask/value pair */
294 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
295                                   const char *buf,unsigned int len,
296                                   int *maskptr,int *valptr)
297 {
298         if (!cptr) return -EINVAL;
299         if (!cptr->info->sym_to_val) return -EINVAL;
300         return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
301 }
302
303
304 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
305                                        const char **names,
306                                        char *ptr,unsigned int len)
307 {
308         unsigned int idx;
309         long sm,um;
310         int spcFl;
311         unsigned int uc,cnt;
312         const char *idStr;
313
314         spcFl = 0;
315         uc = 0;
316         um = 0;
317         for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
318                 if (sm & msk) {
319                         msk &= ~sm;
320                         idStr = names[idx];
321                         if (idStr) {
322                                 cnt = scnprintf(ptr,len,"%s%s%s",
323                                                 (spcFl ? " " : ""),
324                                                 (msk_only ? "" :
325                                                  ((val & sm) ? "+" : "-")),
326                                                 idStr);
327                                 ptr += cnt; len -= cnt; uc += cnt;
328                                 spcFl = !0;
329                         } else {
330                                 um |= sm;
331                         }
332                 }
333         }
334         if (um) {
335                 if (msk_only) {
336                         cnt = scnprintf(ptr,len,"%s0x%lx",
337                                         (spcFl ? " " : ""),
338                                         um);
339                         ptr += cnt; len -= cnt; uc += cnt;
340                         spcFl = !0;
341                 } else if (um & val) {
342                         cnt = scnprintf(ptr,len,"%s+0x%lx",
343                                         (spcFl ? " " : ""),
344                                         um & val);
345                         ptr += cnt; len -= cnt; uc += cnt;
346                         spcFl = !0;
347                 } else if (um & ~val) {
348                         cnt = scnprintf(ptr,len,"%s+0x%lx",
349                                         (spcFl ? " " : ""),
350                                         um & ~val);
351                         ptr += cnt; len -= cnt; uc += cnt;
352                         spcFl = !0;
353                 }
354         }
355         return uc;
356 }
357
358
359 static const char *boolNames[] = {
360         "false",
361         "true",
362         "no",
363         "yes",
364 };
365
366
367 static int parse_token(const char *ptr,unsigned int len,
368                        int *valptr,
369                        const char **names,unsigned int namecnt)
370 {
371         char buf[33];
372         unsigned int slen;
373         unsigned int idx;
374         int negfl;
375         char *p2;
376         *valptr = 0;
377         if (!names) namecnt = 0;
378         for (idx = 0; idx < namecnt; idx++) {
379                 if (!names[idx]) continue;
380                 slen = strlen(names[idx]);
381                 if (slen != len) continue;
382                 if (memcmp(names[idx],ptr,slen)) continue;
383                 *valptr = idx;
384                 return 0;
385         }
386         negfl = 0;
387         if ((*ptr == '-') || (*ptr == '+')) {
388                 negfl = (*ptr == '-');
389                 ptr++; len--;
390         }
391         if (len >= sizeof(buf)) return -EINVAL;
392         memcpy(buf,ptr,len);
393         buf[len] = 0;
394         *valptr = simple_strtol(buf,&p2,0);
395         if (negfl) *valptr = -(*valptr);
396         if (*p2) return -EINVAL;
397         return 1;
398 }
399
400
401 static int parse_mtoken(const char *ptr,unsigned int len,
402                         int *valptr,
403                         const char **names,int valid_bits)
404 {
405         char buf[33];
406         unsigned int slen;
407         unsigned int idx;
408         char *p2;
409         int msk;
410         *valptr = 0;
411         for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
412                 if (!(msk & valid_bits)) continue;
413                 valid_bits &= ~msk;
414                 if (!names[idx]) continue;
415                 slen = strlen(names[idx]);
416                 if (slen != len) continue;
417                 if (memcmp(names[idx],ptr,slen)) continue;
418                 *valptr = msk;
419                 return 0;
420         }
421         if (len >= sizeof(buf)) return -EINVAL;
422         memcpy(buf,ptr,len);
423         buf[len] = 0;
424         *valptr = simple_strtol(buf,&p2,0);
425         if (*p2) return -EINVAL;
426         return 0;
427 }
428
429
430 static int parse_tlist(const char *ptr,unsigned int len,
431                        int *maskptr,int *valptr,
432                        const char **names,int valid_bits)
433 {
434         unsigned int cnt;
435         int mask,val,kv,mode,ret;
436         mask = 0;
437         val = 0;
438         ret = 0;
439         while (len) {
440                 cnt = 0;
441                 while ((cnt < len) &&
442                        ((ptr[cnt] <= 32) ||
443                         (ptr[cnt] >= 127))) cnt++;
444                 ptr += cnt;
445                 len -= cnt;
446                 mode = 0;
447                 if ((*ptr == '-') || (*ptr == '+')) {
448                         mode = (*ptr == '-') ? -1 : 1;
449                         ptr++;
450                         len--;
451                 }
452                 cnt = 0;
453                 while (cnt < len) {
454                         if (ptr[cnt] <= 32) break;
455                         if (ptr[cnt] >= 127) break;
456                         cnt++;
457                 }
458                 if (!cnt) break;
459                 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
460                         ret = -EINVAL;
461                         break;
462                 }
463                 ptr += cnt;
464                 len -= cnt;
465                 switch (mode) {
466                 case 0:
467                         mask = valid_bits;
468                         val |= kv;
469                         break;
470                 case -1:
471                         mask |= kv;
472                         val &= ~kv;
473                         break;
474                 case 1:
475                         mask |= kv;
476                         val |= kv;
477                         break;
478                 default:
479                         break;
480                 }
481         }
482         *maskptr = mask;
483         *valptr = val;
484         return ret;
485 }
486
487
488 /* Convert a symbolic value to a mask/value pair */
489 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
490                            const char *ptr,unsigned int len,
491                            int *maskptr,int *valptr)
492 {
493         int ret = -EINVAL;
494         unsigned int cnt;
495
496         *maskptr = 0;
497         *valptr = 0;
498
499         cnt = 0;
500         while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
501         len -= cnt; ptr += cnt;
502         cnt = 0;
503         while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
504                                (ptr[len-(cnt+1)] >= 127))) cnt++;
505         len -= cnt;
506
507         if (!len) return -EINVAL;
508
509         LOCK_TAKE(cptr->hdw->big_lock); do {
510                 if (cptr->info->type == pvr2_ctl_int) {
511                         ret = parse_token(ptr,len,valptr,NULL,0);
512                         if (ret >= 0) {
513                                 ret = pvr2_ctrl_range_check(cptr,*valptr);
514                         }
515                         if (maskptr) *maskptr = ~0;
516                 } else if (cptr->info->type == pvr2_ctl_bool) {
517                         ret = parse_token(ptr,len,valptr,boolNames,
518                                           ARRAY_SIZE(boolNames));
519                         if (ret == 1) {
520                                 *valptr = *valptr ? !0 : 0;
521                         } else if (ret == 0) {
522                                 *valptr = (*valptr & 1) ? !0 : 0;
523                         }
524                         if (maskptr) *maskptr = 1;
525                 } else if (cptr->info->type == pvr2_ctl_enum) {
526                         ret = parse_token(
527                                 ptr,len,valptr,
528                                 cptr->info->def.type_enum.value_names,
529                                 cptr->info->def.type_enum.count);
530                         if (ret >= 0) {
531                                 ret = pvr2_ctrl_range_check(cptr,*valptr);
532                         }
533                         if (maskptr) *maskptr = ~0;
534                 } else if (cptr->info->type == pvr2_ctl_bitmask) {
535                         ret = parse_tlist(
536                                 ptr,len,maskptr,valptr,
537                                 cptr->info->def.type_bitmask.bit_names,
538                                 cptr->info->def.type_bitmask.valid_bits);
539                 }
540         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
541         return ret;
542 }
543
544
545 /* Convert a given mask/val to a symbolic value */
546 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
547                                     int mask,int val,
548                                     char *buf,unsigned int maxlen,
549                                     unsigned int *len)
550 {
551         int ret = -EINVAL;
552
553         *len = 0;
554         if (cptr->info->type == pvr2_ctl_int) {
555                 *len = scnprintf(buf,maxlen,"%d",val);
556                 ret = 0;
557         } else if (cptr->info->type == pvr2_ctl_bool) {
558                 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
559                 ret = 0;
560         } else if (cptr->info->type == pvr2_ctl_enum) {
561                 const char **names;
562                 names = cptr->info->def.type_enum.value_names;
563                 if ((val >= 0) &&
564                     (val < cptr->info->def.type_enum.count)) {
565                         if (names[val]) {
566                                 *len = scnprintf(
567                                         buf,maxlen,"%s",
568                                         names[val]);
569                         } else {
570                                 *len = 0;
571                         }
572                         ret = 0;
573                 }
574         } else if (cptr->info->type == pvr2_ctl_bitmask) {
575                 *len = gen_bitmask_string(
576                         val & mask & cptr->info->def.type_bitmask.valid_bits,
577                         ~0,!0,
578                         cptr->info->def.type_bitmask.bit_names,
579                         buf,maxlen);
580         }
581         return ret;
582 }
583
584
585 /* Convert a given mask/val to a symbolic value */
586 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
587                            int mask,int val,
588                            char *buf,unsigned int maxlen,
589                            unsigned int *len)
590 {
591         int ret;
592         LOCK_TAKE(cptr->hdw->big_lock); do {
593                 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
594                                                       buf,maxlen,len);
595         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
596         return ret;
597 }
598
599
600 /*
601   Stuff for Emacs to see, in order to encourage consistent editing style:
602   *** Local Variables: ***
603   *** mode: c ***
604   *** fill-column: 75 ***
605   *** tab-width: 8 ***
606   *** c-basic-offset: 8 ***
607   *** End: ***
608   */