V4L/DVB (4239): Handle boolean controls in pvrusb2
authorMike Isely <isely@pobox.com>
Sun, 25 Jun 2006 23:04:40 +0000 (20:04 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Tue, 27 Jun 2006 03:17:27 +0000 (00:17 -0300)
Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-ctrl.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c

index 3577d5bfa007f54fbab918116f8e535a27fd6804..d644afec5a5c6262cae411adacfc9376c5d97bf8 100644 (file)
@@ -53,6 +53,8 @@ int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
                                if (val >= cptr->info->def.type_enum.count) {
                                        break;
                                }
+                       } else if (cptr->info->type != pvr2_ctl_bool) {
+                               break;
                        }
                        ret = cptr->info->set_value(cptr,mask,val);
                } else {
@@ -308,6 +310,14 @@ static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
 }
 
 
+static const char *boolNames[] = {
+       "false",
+       "true",
+       "no",
+       "yes",
+};
+
+
 static int parse_token(const char *ptr,unsigned int len,
                       int *valptr,
                       const char **names,unsigned int namecnt)
@@ -338,7 +348,7 @@ static int parse_token(const char *ptr,unsigned int len,
        *valptr = simple_strtol(buf,&p2,0);
        if (negfl) *valptr = -(*valptr);
        if (*p2) return -EINVAL;
-       return 0;
+       return 1;
 }
 
 
@@ -453,21 +463,31 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
        LOCK_TAKE(cptr->hdw->big_lock); do {
                if (cptr->info->type == pvr2_ctl_int) {
                        ret = parse_token(ptr,len,valptr,0,0);
-                       if ((ret == 0) &&
+                       if ((ret >= 0) &&
                            ((*valptr < cptr->info->def.type_int.min_value) ||
                             (*valptr > cptr->info->def.type_int.max_value))) {
-                               ret = -EINVAL;
+                               ret = -ERANGE;
                        }
                        if (maskptr) *maskptr = ~0;
+               } else if (cptr->info->type == pvr2_ctl_bool) {
+                       ret = parse_token(
+                               ptr,len,valptr,boolNames,
+                               sizeof(boolNames)/sizeof(boolNames[0]));
+                       if (ret == 1) {
+                               *valptr = *valptr ? !0 : 0;
+                       } else if (ret == 0) {
+                               *valptr = (*valptr & 1) ? !0 : 0;
+                       }
+                       if (maskptr) *maskptr = 1;
                } else if (cptr->info->type == pvr2_ctl_enum) {
                        ret = parse_token(
                                ptr,len,valptr,
                                cptr->info->def.type_enum.value_names,
                                cptr->info->def.type_enum.count);
-                       if ((ret == 0) &&
+                       if ((ret >= 0) &&
                            ((*valptr < 0) ||
                             (*valptr >= cptr->info->def.type_enum.count))) {
-                               ret = -EINVAL;
+                               ret = -ERANGE;
                        }
                        if (maskptr) *maskptr = ~0;
                } else if (cptr->info->type == pvr2_ctl_bitmask) {
@@ -493,6 +513,9 @@ int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
        if (cptr->info->type == pvr2_ctl_int) {
                *len = scnprintf(buf,maxlen,"%d",val);
                ret = 0;
+       } else if (cptr->info->type == pvr2_ctl_bool) {
+               *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
+               ret = 0;
        } else if (cptr->info->type == pvr2_ctl_enum) {
                const char **names;
                names = cptr->info->def.type_enum.value_names;
index 9d74151a37da90de7e5b8a14b5e05319f09c2779..bf4cf65441fb0c561762e4bf5e081bec1aa30942 100644 (file)
@@ -27,6 +27,7 @@ enum pvr2_ctl_type {
        pvr2_ctl_int = 0,
        pvr2_ctl_enum = 1,
        pvr2_ctl_bitmask = 2,
+       pvr2_ctl_bool = 3,
 };
 
 
index 872705633048116483a917c6c468e3347a6a76f2..7d46bc10179aae8436a0e4d3636e2e5e7d2ea864 100644 (file)
@@ -436,6 +436,9 @@ static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr)
        .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
        .def.type_enum.value_names = tab
 
+#define DEFBOOL \
+       .type = pvr2_ctl_bool
+
 #define DEFMASK(msk,tab) \
        .type = pvr2_ctl_bitmask, \
        .def.type_bitmask.valid_bits = msk, \
@@ -548,7 +551,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "mute",
                .default_value = 0,
                DEFREF(mute),
-               DEFINT(0,1),
+               DEFBOOL,
        },{
                .desc = "Video Source",
                .name = "input",
@@ -597,7 +600,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "audio_crc",
                .default_value = 1,
                DEFREF(audiocrc),
-               DEFINT(0,1),
+               DEFBOOL,
        },{
                .v4l_id = V4L2_CID_PVR_AUDIOEMPHASIS,
                .desc = "Audio Emphasis",
@@ -611,7 +614,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .name = "vbr",
                .default_value = 0,
                DEFREF(vbr),
-               DEFINT(0,1),
+               DEFBOOL,
        },{
                .v4l_id = V4L2_CID_PVR_VIDEOBITRATE,
                .desc = "Average video bitrate",
@@ -632,7 +635,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .internal_id = PVR2_CID_INTERLACE,
                .default_value = 0,
                DEFREF(interlace),
-               DEFINT(0,1),
+               DEFBOOL,
        },{
                .desc = "Audio Layer",
                .name = "audio_layer",
@@ -671,7 +674,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .desc = "Streaming Enabled",
                .name = "streaming_enabled",
                .get_value = ctrl_streamingenabled_get,
-               DEFINT(0,1),
+               DEFBOOL,
        },{
                .desc = "USB Speed",
                .name = "usb_speed",
@@ -681,7 +684,7 @@ static const struct pvr2_ctl_info control_defs[] = {
                .desc = "Signal Present",
                .name = "signal_present",
                .get_value = ctrl_signal_get,
-               DEFINT(0,1),
+               DEFBOOL,
        },{
                .desc = "Video Standards Available Mask",
                .name = "video_standard_mask_available",
@@ -2007,6 +2010,7 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
        switch (tp) {
        case pvr2_ctl_int: return "integer";
        case pvr2_ctl_enum: return "enum";
+       case pvr2_ctl_bool: return "boolean";
        case pvr2_ctl_bitmask: return "bitmask";
        }
        return "";
index 42540627e30d172b0686fcf2affffc9a40284a3e..c6e6523d74b43dd3df9ecc5ab50405198b9c43f9 100644 (file)
@@ -55,6 +55,7 @@ struct pvr2_sysfs_debugifc {
 
 struct pvr2_sysfs_ctl_item {
        struct class_device_attribute attr_name;
+       struct class_device_attribute attr_type;
        struct class_device_attribute attr_min;
        struct class_device_attribute attr_max;
        struct class_device_attribute attr_enum;
@@ -64,7 +65,7 @@ struct pvr2_sysfs_ctl_item {
        struct pvr2_ctrl *cptr;
        struct pvr2_sysfs *chptr;
        struct pvr2_sysfs_ctl_item *item_next;
-       struct attribute *attr_gen[6];
+       struct attribute *attr_gen[7];
        struct attribute_group grp;
        char name[80];
 };
@@ -92,6 +93,33 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
        return scnprintf(buf,PAGE_SIZE,"%s\n",name);
 }
 
+static ssize_t show_type(int id,struct class_device *class_dev,char *buf)
+{
+       struct pvr2_ctrl *cptr;
+       struct pvr2_sysfs *sfp;
+       const char *name;
+       enum pvr2_ctl_type tp;
+
+       sfp = (struct pvr2_sysfs *)class_dev->class_data;
+       if (!sfp) return -EINVAL;
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+       if (!cptr) return -EINVAL;
+
+       tp = pvr2_ctrl_get_type(cptr);
+       switch (tp) {
+       case pvr2_ctl_int: name = "integer"; break;
+       case pvr2_ctl_enum: name = "enum"; break;
+       case pvr2_ctl_bitmask: name = "bitmask"; break;
+       case pvr2_ctl_bool: name = "boolean"; break;
+       default: name = "?"; break;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name);
+
+       if (!name) return -EINVAL;
+
+       return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+}
+
 static ssize_t show_min(int id,struct class_device *class_dev,char *buf)
 {
        struct pvr2_ctrl *cptr;
@@ -289,6 +317,7 @@ static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf
 
 #define CREATE_BATCH(ctl_id) \
 CREATE_SHOW_INSTANCE(show_name,ctl_id) \
+CREATE_SHOW_INSTANCE(show_type,ctl_id) \
 CREATE_SHOW_INSTANCE(show_min,ctl_id) \
 CREATE_SHOW_INSTANCE(show_max,ctl_id) \
 CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
@@ -361,6 +390,7 @@ CREATE_BATCH(59)
 
 struct pvr2_sysfs_func_set {
        ssize_t (*show_name)(struct class_device *,char *);
+       ssize_t (*show_type)(struct class_device *,char *);
        ssize_t (*show_min)(struct class_device *,char *);
        ssize_t (*show_max)(struct class_device *,char *);
        ssize_t (*show_enum)(struct class_device *,char *);
@@ -376,6 +406,7 @@ struct pvr2_sysfs_func_set {
 #define INIT_BATCH(ctl_id) \
 [ctl_id] = { \
     .show_name = show_name_##ctl_id, \
+    .show_type = show_type_##ctl_id, \
     .show_min = show_min_##ctl_id, \
     .show_max = show_max_##ctl_id, \
     .show_enum = show_enum_##ctl_id, \
@@ -486,6 +517,11 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
        cip->attr_name.attr.mode = S_IRUGO;
        cip->attr_name.show = fp->show_name;
 
+       cip->attr_type.attr.owner = THIS_MODULE;
+       cip->attr_type.attr.name = "type";
+       cip->attr_type.attr.mode = S_IRUGO;
+       cip->attr_type.show = fp->show_type;
+
        cip->attr_min.attr.owner = THIS_MODULE;
        cip->attr_min.attr.name = "min_val";
        cip->attr_min.attr.mode = S_IRUGO;
@@ -521,6 +557,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
 
        acnt = 0;
        cip->attr_gen[acnt++] = &cip->attr_name.attr;
+       cip->attr_gen[acnt++] = &cip->attr_type.attr;
        cip->attr_gen[acnt++] = &cip->attr_val.attr;
        cip->attr_val.show = fp->show_val_norm;
        cip->attr_val.store = fp->store_val_norm;
index da5d8fd9b09bab0299199bfc2f91a16ed8239405..72f28a8e1fe3b3a88161c5fe6594107bee1c8422 100644 (file)
@@ -534,6 +534,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
                        vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
                        vc->step = 1;
                        break;
+               case pvr2_ctl_bool:
+                       vc->type = V4L2_CTRL_TYPE_INTEGER;
+                       vc->minimum = 0;
+                       vc->maximum = 1;
+                       vc->step = 1;
+                       break;
                case pvr2_ctl_int:
                        vc->type = V4L2_CTRL_TYPE_INTEGER;
                        vc->minimum = pvr2_ctrl_get_min(cptr);