Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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