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 {
}
+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)
*valptr = simple_strtol(buf,&p2,0);
if (negfl) *valptr = -(*valptr);
if (*p2) return -EINVAL;
- return 0;
+ return 1;
}
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) {
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;
.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, \
.name = "mute",
.default_value = 0,
DEFREF(mute),
- DEFINT(0,1),
+ DEFBOOL,
},{
.desc = "Video Source",
.name = "input",
.name = "audio_crc",
.default_value = 1,
DEFREF(audiocrc),
- DEFINT(0,1),
+ DEFBOOL,
},{
.v4l_id = V4L2_CID_PVR_AUDIOEMPHASIS,
.desc = "Audio Emphasis",
.name = "vbr",
.default_value = 0,
DEFREF(vbr),
- DEFINT(0,1),
+ DEFBOOL,
},{
.v4l_id = V4L2_CID_PVR_VIDEOBITRATE,
.desc = "Average video bitrate",
.internal_id = PVR2_CID_INTERLACE,
.default_value = 0,
DEFREF(interlace),
- DEFINT(0,1),
+ DEFBOOL,
},{
.desc = "Audio Layer",
.name = "audio_layer",
.desc = "Streaming Enabled",
.name = "streaming_enabled",
.get_value = ctrl_streamingenabled_get,
- DEFINT(0,1),
+ DEFBOOL,
},{
.desc = "USB Speed",
.name = "usb_speed",
.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",
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 "";
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;
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];
};
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;
#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) \
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 *);
#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, \
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;
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;