Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
0005  */
0006 
0007 #include "pvrusb2-ctrl.h"
0008 #include "pvrusb2-hdw-internal.h"
0009 #include <linux/errno.h>
0010 #include <linux/string.h>
0011 #include <linux/mutex.h>
0012 
0013 
0014 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
0015 {
0016     if (cptr->info->check_value) {
0017         if (!cptr->info->check_value(cptr,val)) return -ERANGE;
0018     } else if (cptr->info->type == pvr2_ctl_enum) {
0019         if (val < 0) return -ERANGE;
0020         if (val >= cptr->info->def.type_enum.count) return -ERANGE;
0021     } else {
0022         int lim;
0023         lim = cptr->info->def.type_int.min_value;
0024         if (cptr->info->get_min_value) {
0025             cptr->info->get_min_value(cptr,&lim);
0026         }
0027         if (val < lim) return -ERANGE;
0028         lim = cptr->info->def.type_int.max_value;
0029         if (cptr->info->get_max_value) {
0030             cptr->info->get_max_value(cptr,&lim);
0031         }
0032         if (val > lim) return -ERANGE;
0033     }
0034     return 0;
0035 }
0036 
0037 
0038 /* Set the given control. */
0039 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
0040 {
0041     return pvr2_ctrl_set_mask_value(cptr,~0,val);
0042 }
0043 
0044 
0045 /* Set/clear specific bits of the given control. */
0046 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
0047 {
0048     int ret = 0;
0049     if (!cptr) return -EINVAL;
0050     LOCK_TAKE(cptr->hdw->big_lock); do {
0051         if (cptr->info->set_value) {
0052             if (cptr->info->type == pvr2_ctl_bitmask) {
0053                 mask &= cptr->info->def.type_bitmask.valid_bits;
0054             } else if ((cptr->info->type == pvr2_ctl_int)||
0055                    (cptr->info->type == pvr2_ctl_enum)) {
0056                 ret = pvr2_ctrl_range_check(cptr,val);
0057                 if (ret < 0) break;
0058             } else if (cptr->info->type != pvr2_ctl_bool) {
0059                 break;
0060             }
0061             ret = cptr->info->set_value(cptr,mask,val);
0062         } else {
0063             ret = -EPERM;
0064         }
0065     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0066     return ret;
0067 }
0068 
0069 
0070 /* Get the current value of the given control. */
0071 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
0072 {
0073     int ret = 0;
0074     if (!cptr) return -EINVAL;
0075     LOCK_TAKE(cptr->hdw->big_lock); do {
0076         ret = cptr->info->get_value(cptr,valptr);
0077     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0078     return ret;
0079 }
0080 
0081 
0082 /* Retrieve control's type */
0083 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
0084 {
0085     if (!cptr) return pvr2_ctl_int;
0086     return cptr->info->type;
0087 }
0088 
0089 
0090 /* Retrieve control's maximum value (int type) */
0091 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
0092 {
0093     int ret = 0;
0094     if (!cptr) return 0;
0095     LOCK_TAKE(cptr->hdw->big_lock); do {
0096         if (cptr->info->get_max_value) {
0097             cptr->info->get_max_value(cptr,&ret);
0098         } else if (cptr->info->type == pvr2_ctl_int) {
0099             ret = cptr->info->def.type_int.max_value;
0100         }
0101     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0102     return ret;
0103 }
0104 
0105 
0106 /* Retrieve control's minimum value (int type) */
0107 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
0108 {
0109     int ret = 0;
0110     if (!cptr) return 0;
0111     LOCK_TAKE(cptr->hdw->big_lock); do {
0112         if (cptr->info->get_min_value) {
0113             cptr->info->get_min_value(cptr,&ret);
0114         } else if (cptr->info->type == pvr2_ctl_int) {
0115             ret = cptr->info->def.type_int.min_value;
0116         }
0117     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0118     return ret;
0119 }
0120 
0121 
0122 /* Retrieve control's default value (any type) */
0123 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
0124 {
0125     int ret = 0;
0126     if (!cptr) return -EINVAL;
0127     LOCK_TAKE(cptr->hdw->big_lock); do {
0128         if (cptr->info->get_def_value) {
0129             ret = cptr->info->get_def_value(cptr, valptr);
0130         } else {
0131             *valptr = cptr->info->default_value;
0132         }
0133     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0134     return ret;
0135 }
0136 
0137 
0138 /* Retrieve control's enumeration count (enum only) */
0139 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
0140 {
0141     int ret = 0;
0142     if (!cptr) return 0;
0143     LOCK_TAKE(cptr->hdw->big_lock); do {
0144         if (cptr->info->type == pvr2_ctl_enum) {
0145             ret = cptr->info->def.type_enum.count;
0146         }
0147     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0148     return ret;
0149 }
0150 
0151 
0152 /* Retrieve control's valid mask bits (bit mask only) */
0153 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
0154 {
0155     int ret = 0;
0156     if (!cptr) return 0;
0157     LOCK_TAKE(cptr->hdw->big_lock); do {
0158         if (cptr->info->type == pvr2_ctl_bitmask) {
0159             ret = cptr->info->def.type_bitmask.valid_bits;
0160         }
0161     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0162     return ret;
0163 }
0164 
0165 
0166 /* Retrieve the control's name */
0167 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
0168 {
0169     if (!cptr) return NULL;
0170     return cptr->info->name;
0171 }
0172 
0173 
0174 /* Retrieve the control's desc */
0175 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
0176 {
0177     if (!cptr) return NULL;
0178     return cptr->info->desc;
0179 }
0180 
0181 
0182 /* Retrieve a control enumeration or bit mask value */
0183 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
0184               char *bptr,unsigned int bmax,
0185               unsigned int *blen)
0186 {
0187     int ret = -EINVAL;
0188     if (!cptr) return 0;
0189     *blen = 0;
0190     LOCK_TAKE(cptr->hdw->big_lock); do {
0191         if (cptr->info->type == pvr2_ctl_enum) {
0192             const char * const *names;
0193             names = cptr->info->def.type_enum.value_names;
0194             if (pvr2_ctrl_range_check(cptr,val) == 0) {
0195                 if (names[val]) {
0196                     *blen = scnprintf(
0197                         bptr,bmax,"%s",
0198                         names[val]);
0199                 } else {
0200                     *blen = 0;
0201                 }
0202                 ret = 0;
0203             }
0204         } else if (cptr->info->type == pvr2_ctl_bitmask) {
0205             const char **names;
0206             unsigned int idx;
0207             int msk;
0208             names = cptr->info->def.type_bitmask.bit_names;
0209             val &= cptr->info->def.type_bitmask.valid_bits;
0210             for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
0211                 if (val & msk) {
0212                     *blen = scnprintf(bptr,bmax,"%s",
0213                               names[idx]);
0214                     ret = 0;
0215                     break;
0216                 }
0217             }
0218         }
0219     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0220     return ret;
0221 }
0222 
0223 
0224 /* Return V4L ID for this control or zero if none */
0225 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
0226 {
0227     if (!cptr) return 0;
0228     return cptr->info->v4l_id;
0229 }
0230 
0231 
0232 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
0233 {
0234     unsigned int flags = 0;
0235 
0236     if (cptr->info->get_v4lflags) {
0237         flags = cptr->info->get_v4lflags(cptr);
0238     }
0239 
0240     if (cptr->info->set_value) {
0241         flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
0242     } else {
0243         flags |= V4L2_CTRL_FLAG_READ_ONLY;
0244     }
0245 
0246     return flags;
0247 }
0248 
0249 
0250 /* Return true if control is writable */
0251 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
0252 {
0253     if (!cptr) return 0;
0254     return cptr->info->set_value != NULL;
0255 }
0256 
0257 
0258 /* Return true if control has custom symbolic representation */
0259 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
0260 {
0261     if (!cptr) return 0;
0262     if (!cptr->info->val_to_sym) return 0;
0263     if (!cptr->info->sym_to_val) return 0;
0264     return !0;
0265 }
0266 
0267 
0268 /* Convert a given mask/val to a custom symbolic value */
0269 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
0270                   int mask,int val,
0271                   char *buf,unsigned int maxlen,
0272                   unsigned int *len)
0273 {
0274     if (!cptr) return -EINVAL;
0275     if (!cptr->info->val_to_sym) return -EINVAL;
0276     return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
0277 }
0278 
0279 
0280 /* Convert a symbolic value to a mask/value pair */
0281 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
0282                   const char *buf,unsigned int len,
0283                   int *maskptr,int *valptr)
0284 {
0285     if (!cptr) return -EINVAL;
0286     if (!cptr->info->sym_to_val) return -EINVAL;
0287     return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
0288 }
0289 
0290 
0291 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
0292                        const char **names,
0293                        char *ptr,unsigned int len)
0294 {
0295     unsigned int idx;
0296     long sm,um;
0297     int spcFl;
0298     unsigned int uc,cnt;
0299     const char *idStr;
0300 
0301     spcFl = 0;
0302     uc = 0;
0303     um = 0;
0304     for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
0305         if (sm & msk) {
0306             msk &= ~sm;
0307             idStr = names[idx];
0308             if (idStr) {
0309                 cnt = scnprintf(ptr,len,"%s%s%s",
0310                         (spcFl ? " " : ""),
0311                         (msk_only ? "" :
0312                          ((val & sm) ? "+" : "-")),
0313                         idStr);
0314                 ptr += cnt; len -= cnt; uc += cnt;
0315                 spcFl = !0;
0316             } else {
0317                 um |= sm;
0318             }
0319         }
0320     }
0321     if (um) {
0322         if (msk_only) {
0323             cnt = scnprintf(ptr,len,"%s0x%lx",
0324                     (spcFl ? " " : ""),
0325                     um);
0326             ptr += cnt; len -= cnt; uc += cnt;
0327             spcFl = !0;
0328         } else if (um & val) {
0329             cnt = scnprintf(ptr,len,"%s+0x%lx",
0330                     (spcFl ? " " : ""),
0331                     um & val);
0332             ptr += cnt; len -= cnt; uc += cnt;
0333             spcFl = !0;
0334         } else if (um & ~val) {
0335             cnt = scnprintf(ptr,len,"%s+0x%lx",
0336                     (spcFl ? " " : ""),
0337                     um & ~val);
0338             ptr += cnt; len -= cnt; uc += cnt;
0339             spcFl = !0;
0340         }
0341     }
0342     return uc;
0343 }
0344 
0345 
0346 static const char *boolNames[] = {
0347     "false",
0348     "true",
0349     "no",
0350     "yes",
0351 };
0352 
0353 
0354 static int parse_token(const char *ptr,unsigned int len,
0355                int *valptr,
0356                const char * const *names, unsigned int namecnt)
0357 {
0358     unsigned int slen;
0359     unsigned int idx;
0360     *valptr = 0;
0361     if (!names) namecnt = 0;
0362     for (idx = 0; idx < namecnt; idx++) {
0363         if (!names[idx]) continue;
0364         slen = strlen(names[idx]);
0365         if (slen != len) continue;
0366         if (memcmp(names[idx],ptr,slen)) continue;
0367         *valptr = idx;
0368         return 0;
0369     }
0370     return kstrtoint(ptr, 0, valptr) ? -EINVAL : 1;
0371 }
0372 
0373 
0374 static int parse_mtoken(const char *ptr,unsigned int len,
0375             int *valptr,
0376             const char **names,int valid_bits)
0377 {
0378     unsigned int slen;
0379     unsigned int idx;
0380     int msk;
0381     *valptr = 0;
0382     for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
0383         if (!(msk & valid_bits)) continue;
0384         valid_bits &= ~msk;
0385         if (!names[idx]) continue;
0386         slen = strlen(names[idx]);
0387         if (slen != len) continue;
0388         if (memcmp(names[idx],ptr,slen)) continue;
0389         *valptr = msk;
0390         return 0;
0391     }
0392     return kstrtoint(ptr, 0, valptr);
0393 }
0394 
0395 
0396 static int parse_tlist(const char *ptr,unsigned int len,
0397                int *maskptr,int *valptr,
0398                const char **names,int valid_bits)
0399 {
0400     unsigned int cnt;
0401     int mask,val,kv,mode,ret;
0402     mask = 0;
0403     val = 0;
0404     ret = 0;
0405     while (len) {
0406         cnt = 0;
0407         while ((cnt < len) &&
0408                ((ptr[cnt] <= 32) ||
0409             (ptr[cnt] >= 127))) cnt++;
0410         ptr += cnt;
0411         len -= cnt;
0412         mode = 0;
0413         if ((*ptr == '-') || (*ptr == '+')) {
0414             mode = (*ptr == '-') ? -1 : 1;
0415             ptr++;
0416             len--;
0417         }
0418         cnt = 0;
0419         while (cnt < len) {
0420             if (ptr[cnt] <= 32) break;
0421             if (ptr[cnt] >= 127) break;
0422             cnt++;
0423         }
0424         if (!cnt) break;
0425         if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
0426             ret = -EINVAL;
0427             break;
0428         }
0429         ptr += cnt;
0430         len -= cnt;
0431         switch (mode) {
0432         case 0:
0433             mask = valid_bits;
0434             val |= kv;
0435             break;
0436         case -1:
0437             mask |= kv;
0438             val &= ~kv;
0439             break;
0440         case 1:
0441             mask |= kv;
0442             val |= kv;
0443             break;
0444         default:
0445             break;
0446         }
0447     }
0448     *maskptr = mask;
0449     *valptr = val;
0450     return ret;
0451 }
0452 
0453 
0454 /* Convert a symbolic value to a mask/value pair */
0455 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
0456                const char *ptr,unsigned int len,
0457                int *maskptr,int *valptr)
0458 {
0459     int ret = -EINVAL;
0460     unsigned int cnt;
0461 
0462     *maskptr = 0;
0463     *valptr = 0;
0464 
0465     cnt = 0;
0466     while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
0467     len -= cnt; ptr += cnt;
0468     cnt = 0;
0469     while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
0470                    (ptr[len-(cnt+1)] >= 127))) cnt++;
0471     len -= cnt;
0472 
0473     if (!len) return -EINVAL;
0474 
0475     LOCK_TAKE(cptr->hdw->big_lock); do {
0476         if (cptr->info->type == pvr2_ctl_int) {
0477             ret = parse_token(ptr,len,valptr,NULL,0);
0478             if (ret >= 0) {
0479                 ret = pvr2_ctrl_range_check(cptr,*valptr);
0480             }
0481             *maskptr = ~0;
0482         } else if (cptr->info->type == pvr2_ctl_bool) {
0483             ret = parse_token(ptr,len,valptr,boolNames,
0484                       ARRAY_SIZE(boolNames));
0485             if (ret == 1) {
0486                 *valptr = *valptr ? !0 : 0;
0487             } else if (ret == 0) {
0488                 *valptr = (*valptr & 1) ? !0 : 0;
0489             }
0490             *maskptr = 1;
0491         } else if (cptr->info->type == pvr2_ctl_enum) {
0492             ret = parse_token(
0493                 ptr,len,valptr,
0494                 cptr->info->def.type_enum.value_names,
0495                 cptr->info->def.type_enum.count);
0496             if (ret >= 0) {
0497                 ret = pvr2_ctrl_range_check(cptr,*valptr);
0498             }
0499             *maskptr = ~0;
0500         } else if (cptr->info->type == pvr2_ctl_bitmask) {
0501             ret = parse_tlist(
0502                 ptr,len,maskptr,valptr,
0503                 cptr->info->def.type_bitmask.bit_names,
0504                 cptr->info->def.type_bitmask.valid_bits);
0505         }
0506     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0507     return ret;
0508 }
0509 
0510 
0511 /* Convert a given mask/val to a symbolic value */
0512 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
0513                     int mask,int val,
0514                     char *buf,unsigned int maxlen,
0515                     unsigned int *len)
0516 {
0517     int ret = -EINVAL;
0518 
0519     *len = 0;
0520     if (cptr->info->type == pvr2_ctl_int) {
0521         *len = scnprintf(buf,maxlen,"%d",val);
0522         ret = 0;
0523     } else if (cptr->info->type == pvr2_ctl_bool) {
0524         *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
0525         ret = 0;
0526     } else if (cptr->info->type == pvr2_ctl_enum) {
0527         const char * const *names;
0528         names = cptr->info->def.type_enum.value_names;
0529         if ((val >= 0) &&
0530             (val < cptr->info->def.type_enum.count)) {
0531             if (names[val]) {
0532                 *len = scnprintf(
0533                     buf,maxlen,"%s",
0534                     names[val]);
0535             } else {
0536                 *len = 0;
0537             }
0538             ret = 0;
0539         }
0540     } else if (cptr->info->type == pvr2_ctl_bitmask) {
0541         *len = gen_bitmask_string(
0542             val & mask & cptr->info->def.type_bitmask.valid_bits,
0543             ~0,!0,
0544             cptr->info->def.type_bitmask.bit_names,
0545             buf,maxlen);
0546     }
0547     return ret;
0548 }
0549 
0550 
0551 /* Convert a given mask/val to a symbolic value */
0552 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
0553                int mask,int val,
0554                char *buf,unsigned int maxlen,
0555                unsigned int *len)
0556 {
0557     int ret;
0558     LOCK_TAKE(cptr->hdw->big_lock); do {
0559         ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
0560                               buf,maxlen,len);
0561     } while(0); LOCK_GIVE(cptr->hdw->big_lock);
0562     return ret;
0563 }