diff options
Diffstat (limited to 'linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c')
-rw-r--r-- | linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | 315 |
1 files changed, 140 insertions, 175 deletions
diff --git a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index 053c0b24c..3bf8f166c 100644 --- a/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/linux/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -58,11 +58,13 @@ struct pvr2_sysfs_ctl_item { struct class_device_attribute attr_min; struct class_device_attribute attr_max; struct class_device_attribute attr_enum; + struct class_device_attribute attr_bits; struct class_device_attribute attr_val; + struct class_device_attribute attr_custom; struct pvr2_ctrl *cptr; struct pvr2_sysfs *chptr; struct pvr2_sysfs_ctl_item *item_next; - struct attribute *attr_gen[5]; + struct attribute *attr_gen[6]; struct attribute_group grp; char name[80]; }; @@ -80,7 +82,7 @@ static ssize_t show_name(int id,struct class_device *class_dev,char *buf) sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + if (!cptr) return -EINVAL; name = pvr2_ctrl_get_desc(cptr); pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name); @@ -94,233 +96,171 @@ static ssize_t show_min(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; - int val; + long val; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; - val = pvr2_ctrl_get_min_value(cptr); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %d",sfp,id,val); + if (!cptr) return -EINVAL; + val = pvr2_ctrl_get_min(cptr); - return scnprintf(buf,PAGE_SIZE,"%d\n",val); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val); + + return scnprintf(buf,PAGE_SIZE,"%ld\n",val); } static ssize_t show_max(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; - int val; + long val; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; - val = pvr2_ctrl_get_max_value(cptr); + if (!cptr) return -EINVAL; + val = pvr2_ctrl_get_max(cptr); - pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %d",sfp,id,val); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val); - return scnprintf(buf,PAGE_SIZE,"%d\n",val); + return scnprintf(buf,PAGE_SIZE,"%ld\n",val); } -static ssize_t show_val_int(int id,struct class_device *class_dev,char *buf) +static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; - int val; + int val,ret; + unsigned int cnt = 0; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; - val = pvr2_ctrl_get_value(cptr); + if (!cptr) return -EINVAL; + + ret = pvr2_ctrl_get_value(cptr,&val); + if (ret < 0) return ret; - pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_int(cid=%d) is %d", - sfp,id,val); + ret = pvr2_ctrl_value_to_sym(cptr,~0,val, + buf,PAGE_SIZE-1,&cnt); - return scnprintf(buf,PAGE_SIZE,"%d\n",val); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)", + sfp,id,cnt,buf,val); + buf[cnt] = '\n'; + return cnt+1; } -static ssize_t show_val_enum(int id,struct class_device *class_dev,char *buf) +static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; - int val; - const char *name; + int val,ret; + unsigned int cnt = 0; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; + if (!cptr) return -EINVAL; - val = pvr2_ctrl_get_value(cptr); - name = pvr2_ctrl_get_value_name(cptr,val); + ret = pvr2_ctrl_get_value(cptr,&val); + if (ret < 0) return ret; - pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_enum(cid=%d) is %s (%d)", - sfp,id,name,val); + ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val, + buf,PAGE_SIZE-1,&cnt); - return scnprintf(buf,PAGE_SIZE,"%s\n",name); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)", + sfp,id,cnt,buf,val); + buf[cnt] = '\n'; + return cnt+1; } static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; struct pvr2_sysfs *sfp; - int minval,maxval,val; - const char *name; - ssize_t cnt = 0; + long val; + unsigned int bcnt,ccnt,ecnt; sfp = (struct pvr2_sysfs *)class_dev->class_data; if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; - minval = pvr2_ctrl_get_min_value(cptr); - maxval = pvr2_ctrl_get_max_value(cptr); - for (val = minval; val <= maxval; val++) { - name = pvr2_ctrl_get_value_name(cptr,val); - cnt += scnprintf(buf+cnt,PAGE_SIZE-cnt,"%s\n",name); + if (!cptr) return -EINVAL; + ecnt = pvr2_ctrl_get_cnt(cptr); + bcnt = 0; + for (val = 0; val < ecnt; val++) { + pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); + bcnt += ccnt; + if (bcnt >= PAGE_SIZE) break; + buf[bcnt] = '\n'; + bcnt++; } pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id); - return cnt; + return bcnt; } -static int store_val_any(int id,struct pvr2_sysfs *sfp, - const char *buf,unsigned int count) +static ssize_t show_bits(int id,struct class_device *class_dev,char *buf) { struct pvr2_ctrl *cptr; - int val,minval,maxval; - int ch,ret; - const char *nv; - unsigned int nl; - int negfl; - - /* Trim leading / trailing whitespace */ - while (count) { - ch = buf[0]; - if ((ch > 32) && (ch < 127)) break; - buf++; - count--; - } - while (count) { - ch = buf[count-1]; - if ((ch > 32) && (ch < 127)) break; - count--; - } + struct pvr2_sysfs *sfp; + int valid_bits,msk; + unsigned int bcnt,ccnt; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); - if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL; - - /* Is this an enum? Look for a string value */ - minval = pvr2_ctrl_get_min_value(cptr); - maxval = pvr2_ctrl_get_max_value(cptr); - for (val = minval; val <= maxval; val++) { - nv = pvr2_ctrl_get_value_name(cptr,val); - if ((!nv) && (val == minval)) break; /* Not an enum */ - pvr2_sysfs_trace("pvr2_sysfs(%p) trying ctl_id %d val %d", - sfp,id,val); - if (!nv) { - pvr2_sysfs_trace("pvr2_sysfs(%p) no pointer",sfp); - continue; - } - nl = strlen(nv); - if (nl != count) { - pvr2_sysfs_trace("pvr2_sysfs(%p) count mismatch" - " %d != %d", - sfp,count,nl); - continue; - } - if (memcmp(buf,nv,nl)) { - pvr2_sysfs_trace( - "pvr2_sysfs(%p) name mismatch" - " >>%.*s<< != >>%.*s<<", - sfp,nl,buf,nl,nv); - continue; - } - pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)" - " is enum %s", - sfp,id,nv); - ret = pvr2_ctrl_set_value(cptr,val); - pvr2_hdw_commit_ctl(sfp->channel.hdw); - return 0; - } - if (val > minval) { - pvr2_sysfs_trace( - "pvr2_sysfs(%p) store_val_any(cid=%d)" - " unmatched enum >>%.*s<<", - sfp,id,count,buf); - } - - /* Try to parse as a number */ - negfl = 0; - val = 0; - if (count) { - if (buf[0] == '-') { - negfl = !0; - buf++; - count--; - } else if (buf[0] == '+') { - buf++; - count--; - } - } - while (count) { - ch = buf[0]; - if ((ch < '0') || (ch > '9')) break; - val = val * 10; - val += (ch - '0'); - buf++; - count--; + if (!cptr) return -EINVAL; + valid_bits = pvr2_ctrl_get_mask(cptr); + bcnt = 0; + for (msk = 1; valid_bits; msk <<= 1) { + if (!(msk & valid_bits)) continue; + valid_bits &= ~msk; + pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); + bcnt += ccnt; + if (bcnt >= PAGE_SIZE) break; + buf[bcnt] = '\n'; + bcnt++; } - if (!count) { - if (negfl) val = -val; - pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)" - " int is %d", - sfp,id,val); - - ret = pvr2_ctrl_set_value(cptr,val); - pvr2_hdw_commit_ctl(sfp->channel.hdw); - return ret; - } - - return -EINVAL; + pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id); + return bcnt; } -static int store_val_multi(int id,struct pvr2_sysfs *sfp, - const char *buf,unsigned int count) +static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp, + const char *buf,unsigned int count) { - unsigned int count2; + struct pvr2_ctrl *cptr; int ret; + int mask,val; - while (count) { - count2 = 0; - while ((count2 < count) && (buf[count2] != '\n')) count2++; - ret = store_val_any(id,sfp,buf,count2); - if (ret < 0) return ret; - if (count2 < count) count2++; - buf += count2; - count -= count2; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (customfl) { + ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val); + } else { + ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val); } - return 0; + if (ret < 0) return ret; + ret = pvr2_ctrl_set_mask_value(cptr,mask,val); + pvr2_hdw_commit_ctl(sfp->channel.hdw); + return ret; } -static ssize_t store_val_int(int id,struct class_device *class_dev, +static ssize_t store_val_norm(int id,struct class_device *class_dev, const char *buf,size_t count) { struct pvr2_sysfs *sfp; int ret; sfp = (struct pvr2_sysfs *)class_dev->class_data; - ret = store_val_multi(id,sfp,buf,count); + ret = store_val_any(id,0,sfp,buf,count); if (!ret) ret = count; return ret; } -static ssize_t store_val_enum(int id,struct class_device *class_dev, - const char *buf,size_t count) +static ssize_t store_val_custom(int id,struct class_device *class_dev, + const char *buf,size_t count) { struct pvr2_sysfs *sfp; int ret; sfp = (struct pvr2_sysfs *)class_dev->class_data; - ret = store_val_multi(id,sfp,buf,count); + ret = store_val_any(id,1,sfp,buf,count); if (!ret) ret = count; return ret; } @@ -350,11 +290,12 @@ static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf CREATE_SHOW_INSTANCE(show_name,ctl_id) \ CREATE_SHOW_INSTANCE(show_min,ctl_id) \ CREATE_SHOW_INSTANCE(show_max,ctl_id) \ -CREATE_SHOW_INSTANCE(show_val_int,ctl_id) \ -CREATE_SHOW_INSTANCE(show_val_enum,ctl_id) \ +CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \ +CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \ CREATE_SHOW_INSTANCE(show_enum,ctl_id) \ -CREATE_STORE_INSTANCE(store_val_int,ctl_id) \ -CREATE_STORE_INSTANCE(store_val_enum,ctl_id) +CREATE_SHOW_INSTANCE(show_bits,ctl_id) \ +CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \ +CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \ CREATE_BATCH(0) CREATE_BATCH(1) @@ -396,12 +337,13 @@ struct pvr2_sysfs_func_set { ssize_t (*show_min)(struct class_device *,char *); ssize_t (*show_max)(struct class_device *,char *); ssize_t (*show_enum)(struct class_device *,char *); - ssize_t (*show_val_int)(struct class_device *,char *); - ssize_t (*show_val_enum)(struct class_device *,char *); - ssize_t (*store_val_int)(struct class_device *, - const char *,size_t); - ssize_t (*store_val_enum)(struct class_device *, + ssize_t (*show_bits)(struct class_device *,char *); + ssize_t (*show_val_norm)(struct class_device *,char *); + ssize_t (*store_val_norm)(struct class_device *, const char *,size_t); + ssize_t (*show_val_custom)(struct class_device *,char *); + ssize_t (*store_val_custom)(struct class_device *, + const char *,size_t); }; #define INIT_BATCH(ctl_id) \ @@ -410,10 +352,11 @@ struct pvr2_sysfs_func_set { .show_min = show_min_##ctl_id, \ .show_max = show_max_##ctl_id, \ .show_enum = show_enum_##ctl_id, \ - .show_val_int = show_val_int_##ctl_id, \ - .show_val_enum = show_val_enum_##ctl_id, \ - .store_val_int = store_val_int_##ctl_id, \ - .store_val_enum = store_val_enum_##ctl_id, \ + .show_bits = show_bits_##ctl_id, \ + .show_val_norm = show_val_norm_##ctl_id, \ + .store_val_norm = store_val_norm_##ctl_id, \ + .show_val_custom = show_val_custom_##ctl_id, \ + .store_val_custom = store_val_custom_##ctl_id, \ } \ static struct pvr2_sysfs_func_set funcs[] = { @@ -459,7 +402,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) struct pvr2_sysfs_ctl_item *cip; struct pvr2_sysfs_func_set *fp; struct pvr2_ctrl *cptr; - unsigned int cnt; + unsigned int cnt,acnt; if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { return; @@ -504,28 +447,50 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->attr_val.attr.name = "cur_val"; cip->attr_val.attr.mode = S_IRUGO; + cip->attr_custom.attr.owner = THIS_MODULE; + cip->attr_custom.attr.name = "custom_val"; + cip->attr_custom.attr.mode = S_IRUGO; + cip->attr_enum.attr.owner = THIS_MODULE; cip->attr_enum.attr.name = "enum_val"; cip->attr_enum.attr.mode = S_IRUGO; cip->attr_enum.show = fp->show_enum; - if (pvr2_ctrl_is_writeable(cptr)) { + cip->attr_bits.attr.owner = THIS_MODULE; + cip->attr_bits.attr.name = "bit_val"; + cip->attr_bits.attr.mode = S_IRUGO; + cip->attr_bits.show = fp->show_bits; + + if (pvr2_ctrl_is_writable(cptr)) { cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; + cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP; } - cip->attr_gen[0] = &cip->attr_name.attr; - cip->attr_gen[1] = &cip->attr_val.attr; - if (pvr2_ctrl_get_type(cptr) == PVR2_CTRL_TYPE_ENUM) { + acnt = 0; + cip->attr_gen[acnt++] = &cip->attr_name.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; + if (pvr2_ctrl_has_custom_symbols(cptr)) { + cip->attr_gen[acnt++] = &cip->attr_custom.attr; + cip->attr_custom.show = fp->show_val_custom; + cip->attr_custom.store = fp->store_val_custom; + } + switch (pvr2_ctrl_get_type(cptr)) { + case pvr2_ctl_enum: // Control is an enumeration - cip->attr_gen[2] = &cip->attr_enum.attr; - cip->attr_val.show = fp->show_val_enum; - cip->attr_val.store = fp->store_val_enum; - } else { + cip->attr_gen[acnt++] = &cip->attr_enum.attr; + break; + case pvr2_ctl_int: // Control is an integer - cip->attr_val.show = fp->show_val_int; - cip->attr_val.store = fp->store_val_int; - cip->attr_gen[2] = &cip->attr_min.attr; - cip->attr_gen[3] = &cip->attr_max.attr; + cip->attr_gen[acnt++] = &cip->attr_min.attr; + cip->attr_gen[acnt++] = &cip->attr_max.attr; + break; + case pvr2_ctl_bitmask: + // Control is an bitmask + cip->attr_gen[acnt++] = &cip->attr_bits.attr; + break; + default: break; } cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s", |