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