162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2005 Mike Isely <isely@pobox.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/string.h> 862306a36Sopenharmony_ci#include <linux/slab.h> 962306a36Sopenharmony_ci#include "pvrusb2-sysfs.h" 1062306a36Sopenharmony_ci#include "pvrusb2-hdw.h" 1162306a36Sopenharmony_ci#include "pvrusb2-debug.h" 1262306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 1362306a36Sopenharmony_ci#include "pvrusb2-debugifc.h" 1462306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistruct pvr2_sysfs { 1962306a36Sopenharmony_ci struct pvr2_channel channel; 2062306a36Sopenharmony_ci struct device *class_dev; 2162306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 2262306a36Sopenharmony_ci struct pvr2_sysfs_debugifc *debugifc; 2362306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 2462306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *item_first; 2562306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *item_last; 2662306a36Sopenharmony_ci struct device_attribute attr_v4l_minor_number; 2762306a36Sopenharmony_ci struct device_attribute attr_v4l_radio_minor_number; 2862306a36Sopenharmony_ci struct device_attribute attr_unit_number; 2962306a36Sopenharmony_ci struct device_attribute attr_bus_info; 3062306a36Sopenharmony_ci struct device_attribute attr_hdw_name; 3162306a36Sopenharmony_ci struct device_attribute attr_hdw_desc; 3262306a36Sopenharmony_ci int v4l_minor_number_created_ok; 3362306a36Sopenharmony_ci int v4l_radio_minor_number_created_ok; 3462306a36Sopenharmony_ci int unit_number_created_ok; 3562306a36Sopenharmony_ci int bus_info_created_ok; 3662306a36Sopenharmony_ci int hdw_name_created_ok; 3762306a36Sopenharmony_ci int hdw_desc_created_ok; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 4162306a36Sopenharmony_cistruct pvr2_sysfs_debugifc { 4262306a36Sopenharmony_ci struct device_attribute attr_debugcmd; 4362306a36Sopenharmony_ci struct device_attribute attr_debuginfo; 4462306a36Sopenharmony_ci int debugcmd_created_ok; 4562306a36Sopenharmony_ci int debuginfo_created_ok; 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistruct pvr2_sysfs_ctl_item { 5062306a36Sopenharmony_ci struct device_attribute attr_name; 5162306a36Sopenharmony_ci struct device_attribute attr_type; 5262306a36Sopenharmony_ci struct device_attribute attr_min; 5362306a36Sopenharmony_ci struct device_attribute attr_max; 5462306a36Sopenharmony_ci struct device_attribute attr_def; 5562306a36Sopenharmony_ci struct device_attribute attr_enum; 5662306a36Sopenharmony_ci struct device_attribute attr_bits; 5762306a36Sopenharmony_ci struct device_attribute attr_val; 5862306a36Sopenharmony_ci struct device_attribute attr_custom; 5962306a36Sopenharmony_ci struct pvr2_ctrl *cptr; 6062306a36Sopenharmony_ci int ctl_id; 6162306a36Sopenharmony_ci struct pvr2_sysfs *chptr; 6262306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *item_next; 6362306a36Sopenharmony_ci struct attribute *attr_gen[8]; 6462306a36Sopenharmony_ci struct attribute_group grp; 6562306a36Sopenharmony_ci int created_ok; 6662306a36Sopenharmony_ci char name[80]; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic ssize_t show_name(struct device *class_dev, 7062306a36Sopenharmony_ci struct device_attribute *attr, 7162306a36Sopenharmony_ci char *buf) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 7462306a36Sopenharmony_ci const char *name; 7562306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name); 7662306a36Sopenharmony_ci name = pvr2_ctrl_get_desc(cip->cptr); 7762306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s", 7862306a36Sopenharmony_ci cip->chptr, cip->ctl_id, name); 7962306a36Sopenharmony_ci if (!name) return -EINVAL; 8062306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", name); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic ssize_t show_type(struct device *class_dev, 8462306a36Sopenharmony_ci struct device_attribute *attr, 8562306a36Sopenharmony_ci char *buf) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 8862306a36Sopenharmony_ci const char *name; 8962306a36Sopenharmony_ci enum pvr2_ctl_type tp; 9062306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type); 9162306a36Sopenharmony_ci tp = pvr2_ctrl_get_type(cip->cptr); 9262306a36Sopenharmony_ci switch (tp) { 9362306a36Sopenharmony_ci case pvr2_ctl_int: name = "integer"; break; 9462306a36Sopenharmony_ci case pvr2_ctl_enum: name = "enum"; break; 9562306a36Sopenharmony_ci case pvr2_ctl_bitmask: name = "bitmask"; break; 9662306a36Sopenharmony_ci case pvr2_ctl_bool: name = "boolean"; break; 9762306a36Sopenharmony_ci default: name = "?"; break; 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s", 10062306a36Sopenharmony_ci cip->chptr, cip->ctl_id, name); 10162306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", name); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic ssize_t show_min(struct device *class_dev, 10562306a36Sopenharmony_ci struct device_attribute *attr, 10662306a36Sopenharmony_ci char *buf) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 10962306a36Sopenharmony_ci long val; 11062306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min); 11162306a36Sopenharmony_ci val = pvr2_ctrl_get_min(cip->cptr); 11262306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld", 11362306a36Sopenharmony_ci cip->chptr, cip->ctl_id, val); 11462306a36Sopenharmony_ci return sysfs_emit(buf, "%ld\n", val); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic ssize_t show_max(struct device *class_dev, 11862306a36Sopenharmony_ci struct device_attribute *attr, 11962306a36Sopenharmony_ci char *buf) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 12262306a36Sopenharmony_ci long val; 12362306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max); 12462306a36Sopenharmony_ci val = pvr2_ctrl_get_max(cip->cptr); 12562306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld", 12662306a36Sopenharmony_ci cip->chptr, cip->ctl_id, val); 12762306a36Sopenharmony_ci return sysfs_emit(buf, "%ld\n", val); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic ssize_t show_def(struct device *class_dev, 13162306a36Sopenharmony_ci struct device_attribute *attr, 13262306a36Sopenharmony_ci char *buf) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 13562306a36Sopenharmony_ci int val; 13662306a36Sopenharmony_ci int ret; 13762306a36Sopenharmony_ci unsigned int cnt = 0; 13862306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def); 13962306a36Sopenharmony_ci ret = pvr2_ctrl_get_def(cip->cptr, &val); 14062306a36Sopenharmony_ci if (ret < 0) return ret; 14162306a36Sopenharmony_ci ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val, 14262306a36Sopenharmony_ci buf, PAGE_SIZE - 1, &cnt); 14362306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)", 14462306a36Sopenharmony_ci cip->chptr, cip->ctl_id, cnt, buf, val); 14562306a36Sopenharmony_ci buf[cnt] = '\n'; 14662306a36Sopenharmony_ci return cnt + 1; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic ssize_t show_val_norm(struct device *class_dev, 15062306a36Sopenharmony_ci struct device_attribute *attr, 15162306a36Sopenharmony_ci char *buf) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 15462306a36Sopenharmony_ci int val; 15562306a36Sopenharmony_ci int ret; 15662306a36Sopenharmony_ci unsigned int cnt = 0; 15762306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val); 15862306a36Sopenharmony_ci ret = pvr2_ctrl_get_value(cip->cptr, &val); 15962306a36Sopenharmony_ci if (ret < 0) return ret; 16062306a36Sopenharmony_ci ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val, 16162306a36Sopenharmony_ci buf, PAGE_SIZE - 1, &cnt); 16262306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)", 16362306a36Sopenharmony_ci cip->chptr, cip->ctl_id, cnt, buf, val); 16462306a36Sopenharmony_ci buf[cnt] = '\n'; 16562306a36Sopenharmony_ci return cnt+1; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic ssize_t show_val_custom(struct device *class_dev, 16962306a36Sopenharmony_ci struct device_attribute *attr, 17062306a36Sopenharmony_ci char *buf) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 17362306a36Sopenharmony_ci int val; 17462306a36Sopenharmony_ci int ret; 17562306a36Sopenharmony_ci unsigned int cnt = 0; 17662306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom); 17762306a36Sopenharmony_ci ret = pvr2_ctrl_get_value(cip->cptr, &val); 17862306a36Sopenharmony_ci if (ret < 0) return ret; 17962306a36Sopenharmony_ci ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val, 18062306a36Sopenharmony_ci buf, PAGE_SIZE - 1, &cnt); 18162306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)", 18262306a36Sopenharmony_ci cip->chptr, cip->ctl_id, cnt, buf, val); 18362306a36Sopenharmony_ci buf[cnt] = '\n'; 18462306a36Sopenharmony_ci return cnt+1; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic ssize_t show_enum(struct device *class_dev, 18862306a36Sopenharmony_ci struct device_attribute *attr, 18962306a36Sopenharmony_ci char *buf) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 19262306a36Sopenharmony_ci long val; 19362306a36Sopenharmony_ci unsigned int bcnt, ccnt, ecnt; 19462306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum); 19562306a36Sopenharmony_ci ecnt = pvr2_ctrl_get_cnt(cip->cptr); 19662306a36Sopenharmony_ci bcnt = 0; 19762306a36Sopenharmony_ci for (val = 0; val < ecnt; val++) { 19862306a36Sopenharmony_ci pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt, 19962306a36Sopenharmony_ci PAGE_SIZE - bcnt, &ccnt); 20062306a36Sopenharmony_ci if (!ccnt) continue; 20162306a36Sopenharmony_ci bcnt += ccnt; 20262306a36Sopenharmony_ci if (bcnt >= PAGE_SIZE) break; 20362306a36Sopenharmony_ci buf[bcnt] = '\n'; 20462306a36Sopenharmony_ci bcnt++; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)", 20762306a36Sopenharmony_ci cip->chptr, cip->ctl_id); 20862306a36Sopenharmony_ci return bcnt; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic ssize_t show_bits(struct device *class_dev, 21262306a36Sopenharmony_ci struct device_attribute *attr, 21362306a36Sopenharmony_ci char *buf) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 21662306a36Sopenharmony_ci int valid_bits, msk; 21762306a36Sopenharmony_ci unsigned int bcnt, ccnt; 21862306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits); 21962306a36Sopenharmony_ci valid_bits = pvr2_ctrl_get_mask(cip->cptr); 22062306a36Sopenharmony_ci bcnt = 0; 22162306a36Sopenharmony_ci for (msk = 1; valid_bits; msk <<= 1) { 22262306a36Sopenharmony_ci if (!(msk & valid_bits)) continue; 22362306a36Sopenharmony_ci valid_bits &= ~msk; 22462306a36Sopenharmony_ci pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt, 22562306a36Sopenharmony_ci PAGE_SIZE - bcnt, &ccnt); 22662306a36Sopenharmony_ci bcnt += ccnt; 22762306a36Sopenharmony_ci if (bcnt >= PAGE_SIZE) break; 22862306a36Sopenharmony_ci buf[bcnt] = '\n'; 22962306a36Sopenharmony_ci bcnt++; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)", 23262306a36Sopenharmony_ci cip->chptr, cip->ctl_id); 23362306a36Sopenharmony_ci return bcnt; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl, 23762306a36Sopenharmony_ci const char *buf,unsigned int count) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci int ret; 24062306a36Sopenharmony_ci int mask,val; 24162306a36Sopenharmony_ci if (customfl) { 24262306a36Sopenharmony_ci ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count, 24362306a36Sopenharmony_ci &mask, &val); 24462306a36Sopenharmony_ci } else { 24562306a36Sopenharmony_ci ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count, 24662306a36Sopenharmony_ci &mask, &val); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci if (ret < 0) return ret; 24962306a36Sopenharmony_ci ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val); 25062306a36Sopenharmony_ci pvr2_hdw_commit_ctl(cip->chptr->channel.hdw); 25162306a36Sopenharmony_ci return ret; 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic ssize_t store_val_norm(struct device *class_dev, 25562306a36Sopenharmony_ci struct device_attribute *attr, 25662306a36Sopenharmony_ci const char *buf, size_t count) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 25962306a36Sopenharmony_ci int ret; 26062306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val); 26162306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"", 26262306a36Sopenharmony_ci cip->chptr, cip->ctl_id, (int)count, buf); 26362306a36Sopenharmony_ci ret = store_val_any(cip, 0, buf, count); 26462306a36Sopenharmony_ci if (!ret) ret = count; 26562306a36Sopenharmony_ci return ret; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic ssize_t store_val_custom(struct device *class_dev, 26962306a36Sopenharmony_ci struct device_attribute *attr, 27062306a36Sopenharmony_ci const char *buf, size_t count) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 27362306a36Sopenharmony_ci int ret; 27462306a36Sopenharmony_ci cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom); 27562306a36Sopenharmony_ci pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"", 27662306a36Sopenharmony_ci cip->chptr, cip->ctl_id, (int)count, buf); 27762306a36Sopenharmony_ci ret = store_val_any(cip, 1, buf, count); 27862306a36Sopenharmony_ci if (!ret) ret = count; 27962306a36Sopenharmony_ci return ret; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip; 28562306a36Sopenharmony_ci struct pvr2_ctrl *cptr; 28662306a36Sopenharmony_ci unsigned int cnt,acnt; 28762306a36Sopenharmony_ci int ret; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); 29062306a36Sopenharmony_ci if (!cptr) return; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci cip = kzalloc(sizeof(*cip),GFP_KERNEL); 29362306a36Sopenharmony_ci if (!cip) return; 29462306a36Sopenharmony_ci pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci cip->cptr = cptr; 29762306a36Sopenharmony_ci cip->ctl_id = ctl_id; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci cip->chptr = sfp; 30062306a36Sopenharmony_ci cip->item_next = NULL; 30162306a36Sopenharmony_ci if (sfp->item_last) { 30262306a36Sopenharmony_ci sfp->item_last->item_next = cip; 30362306a36Sopenharmony_ci } else { 30462306a36Sopenharmony_ci sfp->item_first = cip; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci sfp->item_last = cip; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_name.attr); 30962306a36Sopenharmony_ci cip->attr_name.attr.name = "name"; 31062306a36Sopenharmony_ci cip->attr_name.attr.mode = S_IRUGO; 31162306a36Sopenharmony_ci cip->attr_name.show = show_name; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_type.attr); 31462306a36Sopenharmony_ci cip->attr_type.attr.name = "type"; 31562306a36Sopenharmony_ci cip->attr_type.attr.mode = S_IRUGO; 31662306a36Sopenharmony_ci cip->attr_type.show = show_type; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_min.attr); 31962306a36Sopenharmony_ci cip->attr_min.attr.name = "min_val"; 32062306a36Sopenharmony_ci cip->attr_min.attr.mode = S_IRUGO; 32162306a36Sopenharmony_ci cip->attr_min.show = show_min; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_max.attr); 32462306a36Sopenharmony_ci cip->attr_max.attr.name = "max_val"; 32562306a36Sopenharmony_ci cip->attr_max.attr.mode = S_IRUGO; 32662306a36Sopenharmony_ci cip->attr_max.show = show_max; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_def.attr); 32962306a36Sopenharmony_ci cip->attr_def.attr.name = "def_val"; 33062306a36Sopenharmony_ci cip->attr_def.attr.mode = S_IRUGO; 33162306a36Sopenharmony_ci cip->attr_def.show = show_def; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_val.attr); 33462306a36Sopenharmony_ci cip->attr_val.attr.name = "cur_val"; 33562306a36Sopenharmony_ci cip->attr_val.attr.mode = S_IRUGO; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_custom.attr); 33862306a36Sopenharmony_ci cip->attr_custom.attr.name = "custom_val"; 33962306a36Sopenharmony_ci cip->attr_custom.attr.mode = S_IRUGO; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_enum.attr); 34262306a36Sopenharmony_ci cip->attr_enum.attr.name = "enum_val"; 34362306a36Sopenharmony_ci cip->attr_enum.attr.mode = S_IRUGO; 34462306a36Sopenharmony_ci cip->attr_enum.show = show_enum; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci sysfs_attr_init(&cip->attr_bits.attr); 34762306a36Sopenharmony_ci cip->attr_bits.attr.name = "bit_val"; 34862306a36Sopenharmony_ci cip->attr_bits.attr.mode = S_IRUGO; 34962306a36Sopenharmony_ci cip->attr_bits.show = show_bits; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (pvr2_ctrl_is_writable(cptr)) { 35262306a36Sopenharmony_ci cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; 35362306a36Sopenharmony_ci cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci acnt = 0; 35762306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_name.attr; 35862306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_type.attr; 35962306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_val.attr; 36062306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_def.attr; 36162306a36Sopenharmony_ci cip->attr_val.show = show_val_norm; 36262306a36Sopenharmony_ci cip->attr_val.store = store_val_norm; 36362306a36Sopenharmony_ci if (pvr2_ctrl_has_custom_symbols(cptr)) { 36462306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_custom.attr; 36562306a36Sopenharmony_ci cip->attr_custom.show = show_val_custom; 36662306a36Sopenharmony_ci cip->attr_custom.store = store_val_custom; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci switch (pvr2_ctrl_get_type(cptr)) { 36962306a36Sopenharmony_ci case pvr2_ctl_enum: 37062306a36Sopenharmony_ci // Control is an enumeration 37162306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_enum.attr; 37262306a36Sopenharmony_ci break; 37362306a36Sopenharmony_ci case pvr2_ctl_int: 37462306a36Sopenharmony_ci // Control is an integer 37562306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_min.attr; 37662306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_max.attr; 37762306a36Sopenharmony_ci break; 37862306a36Sopenharmony_ci case pvr2_ctl_bitmask: 37962306a36Sopenharmony_ci // Control is an bitmask 38062306a36Sopenharmony_ci cip->attr_gen[acnt++] = &cip->attr_bits.attr; 38162306a36Sopenharmony_ci break; 38262306a36Sopenharmony_ci default: break; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s", 38662306a36Sopenharmony_ci pvr2_ctrl_get_name(cptr)); 38762306a36Sopenharmony_ci cip->name[cnt] = 0; 38862306a36Sopenharmony_ci cip->grp.name = cip->name; 38962306a36Sopenharmony_ci cip->grp.attrs = cip->attr_gen; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); 39262306a36Sopenharmony_ci if (ret) { 39362306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 39462306a36Sopenharmony_ci "sysfs_create_group error: %d", 39562306a36Sopenharmony_ci ret); 39662306a36Sopenharmony_ci return; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci cip->created_ok = !0; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 40262306a36Sopenharmony_cistatic ssize_t debuginfo_show(struct device *, struct device_attribute *, 40362306a36Sopenharmony_ci char *); 40462306a36Sopenharmony_cistatic ssize_t debugcmd_show(struct device *, struct device_attribute *, 40562306a36Sopenharmony_ci char *); 40662306a36Sopenharmony_cistatic ssize_t debugcmd_store(struct device *, struct device_attribute *, 40762306a36Sopenharmony_ci const char *, size_t count); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct pvr2_sysfs_debugifc *dip; 41262306a36Sopenharmony_ci int ret; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci dip = kzalloc(sizeof(*dip),GFP_KERNEL); 41562306a36Sopenharmony_ci if (!dip) return; 41662306a36Sopenharmony_ci sysfs_attr_init(&dip->attr_debugcmd.attr); 41762306a36Sopenharmony_ci dip->attr_debugcmd.attr.name = "debugcmd"; 41862306a36Sopenharmony_ci dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; 41962306a36Sopenharmony_ci dip->attr_debugcmd.show = debugcmd_show; 42062306a36Sopenharmony_ci dip->attr_debugcmd.store = debugcmd_store; 42162306a36Sopenharmony_ci sysfs_attr_init(&dip->attr_debuginfo.attr); 42262306a36Sopenharmony_ci dip->attr_debuginfo.attr.name = "debuginfo"; 42362306a36Sopenharmony_ci dip->attr_debuginfo.attr.mode = S_IRUGO; 42462306a36Sopenharmony_ci dip->attr_debuginfo.show = debuginfo_show; 42562306a36Sopenharmony_ci sfp->debugifc = dip; 42662306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd); 42762306a36Sopenharmony_ci if (ret < 0) { 42862306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 42962306a36Sopenharmony_ci "device_create_file error: %d", 43062306a36Sopenharmony_ci ret); 43162306a36Sopenharmony_ci } else { 43262306a36Sopenharmony_ci dip->debugcmd_created_ok = !0; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo); 43562306a36Sopenharmony_ci if (ret < 0) { 43662306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 43762306a36Sopenharmony_ci "device_create_file error: %d", 43862306a36Sopenharmony_ci ret); 43962306a36Sopenharmony_ci } else { 44062306a36Sopenharmony_ci dip->debuginfo_created_ok = !0; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci if (!sfp->debugifc) return; 44862306a36Sopenharmony_ci if (sfp->debugifc->debuginfo_created_ok) { 44962306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 45062306a36Sopenharmony_ci &sfp->debugifc->attr_debuginfo); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci if (sfp->debugifc->debugcmd_created_ok) { 45362306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 45462306a36Sopenharmony_ci &sfp->debugifc->attr_debugcmd); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci kfree(sfp->debugifc); 45762306a36Sopenharmony_ci sfp->debugifc = NULL; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci unsigned int idx,cnt; 46562306a36Sopenharmony_ci cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw); 46662306a36Sopenharmony_ci for (idx = 0; idx < cnt; idx++) { 46762306a36Sopenharmony_ci pvr2_sysfs_add_control(sfp,idx); 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cistatic void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci struct pvr2_sysfs_ctl_item *cip1,*cip2; 47562306a36Sopenharmony_ci for (cip1 = sfp->item_first; cip1; cip1 = cip2) { 47662306a36Sopenharmony_ci cip2 = cip1->item_next; 47762306a36Sopenharmony_ci if (cip1->created_ok) { 47862306a36Sopenharmony_ci sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); 48162306a36Sopenharmony_ci kfree(cip1); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic void pvr2_sysfs_release(struct device *class_dev) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev); 48962306a36Sopenharmony_ci kfree(class_dev); 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistatic struct class pvr2_class = { 49462306a36Sopenharmony_ci .name = "pvrusb2", 49562306a36Sopenharmony_ci .dev_release = pvr2_sysfs_release, 49662306a36Sopenharmony_ci}; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_cistatic void class_dev_destroy(struct pvr2_sysfs *sfp) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci struct device *dev; 50262306a36Sopenharmony_ci if (!sfp->class_dev) return; 50362306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 50462306a36Sopenharmony_ci pvr2_sysfs_tear_down_debugifc(sfp); 50562306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 50662306a36Sopenharmony_ci pvr2_sysfs_tear_down_controls(sfp); 50762306a36Sopenharmony_ci if (sfp->hdw_desc_created_ok) { 50862306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 50962306a36Sopenharmony_ci &sfp->attr_hdw_desc); 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci if (sfp->hdw_name_created_ok) { 51262306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 51362306a36Sopenharmony_ci &sfp->attr_hdw_name); 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci if (sfp->bus_info_created_ok) { 51662306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 51762306a36Sopenharmony_ci &sfp->attr_bus_info); 51862306a36Sopenharmony_ci } 51962306a36Sopenharmony_ci if (sfp->v4l_minor_number_created_ok) { 52062306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 52162306a36Sopenharmony_ci &sfp->attr_v4l_minor_number); 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci if (sfp->v4l_radio_minor_number_created_ok) { 52462306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 52562306a36Sopenharmony_ci &sfp->attr_v4l_radio_minor_number); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci if (sfp->unit_number_created_ok) { 52862306a36Sopenharmony_ci device_remove_file(sfp->class_dev, 52962306a36Sopenharmony_ci &sfp->attr_unit_number); 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); 53262306a36Sopenharmony_ci dev_set_drvdata(sfp->class_dev, NULL); 53362306a36Sopenharmony_ci dev = sfp->class_dev->parent; 53462306a36Sopenharmony_ci sfp->class_dev->parent = NULL; 53562306a36Sopenharmony_ci put_device(dev); 53662306a36Sopenharmony_ci device_unregister(sfp->class_dev); 53762306a36Sopenharmony_ci sfp->class_dev = NULL; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic ssize_t v4l_minor_number_show(struct device *class_dev, 54262306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 54562306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 54662306a36Sopenharmony_ci if (!sfp) return -EINVAL; 54762306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 54862306a36Sopenharmony_ci pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, 54962306a36Sopenharmony_ci pvr2_v4l_type_video)); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_cistatic ssize_t bus_info_show(struct device *class_dev, 55462306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 55762306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 55862306a36Sopenharmony_ci if (!sfp) return -EINVAL; 55962306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", 56062306a36Sopenharmony_ci pvr2_hdw_get_bus_info(sfp->channel.hdw)); 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cistatic ssize_t hdw_name_show(struct device *class_dev, 56562306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 56862306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 56962306a36Sopenharmony_ci if (!sfp) return -EINVAL; 57062306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", 57162306a36Sopenharmony_ci pvr2_hdw_get_type(sfp->channel.hdw)); 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic ssize_t hdw_desc_show(struct device *class_dev, 57662306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 57962306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 58062306a36Sopenharmony_ci if (!sfp) return -EINVAL; 58162306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", 58262306a36Sopenharmony_ci pvr2_hdw_get_desc(sfp->channel.hdw)); 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cistatic ssize_t v4l_radio_minor_number_show(struct device *class_dev, 58762306a36Sopenharmony_ci struct device_attribute *attr, 58862306a36Sopenharmony_ci char *buf) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 59162306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 59262306a36Sopenharmony_ci if (!sfp) return -EINVAL; 59362306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 59462306a36Sopenharmony_ci pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw, 59562306a36Sopenharmony_ci pvr2_v4l_type_radio)); 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic ssize_t unit_number_show(struct device *class_dev, 60062306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 60362306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 60462306a36Sopenharmony_ci if (!sfp) return -EINVAL; 60562306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", 60662306a36Sopenharmony_ci pvr2_hdw_get_unit_number(sfp->channel.hdw)); 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_cistatic void class_dev_create(struct pvr2_sysfs *sfp) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci struct usb_device *usb_dev; 61362306a36Sopenharmony_ci struct device *class_dev; 61462306a36Sopenharmony_ci int ret; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); 61762306a36Sopenharmony_ci if (!usb_dev) return; 61862306a36Sopenharmony_ci class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL); 61962306a36Sopenharmony_ci if (!class_dev) return; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci class_dev->class = &pvr2_class; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci dev_set_name(class_dev, "%s", 62662306a36Sopenharmony_ci pvr2_hdw_get_device_identifier(sfp->channel.hdw)); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci class_dev->parent = get_device(&usb_dev->dev); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci sfp->class_dev = class_dev; 63162306a36Sopenharmony_ci dev_set_drvdata(class_dev, sfp); 63262306a36Sopenharmony_ci ret = device_register(class_dev); 63362306a36Sopenharmony_ci if (ret) { 63462306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 63562306a36Sopenharmony_ci "device_register failed"); 63662306a36Sopenharmony_ci put_device(class_dev); 63762306a36Sopenharmony_ci return; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci sysfs_attr_init(&sfp->attr_v4l_minor_number.attr); 64162306a36Sopenharmony_ci sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; 64262306a36Sopenharmony_ci sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; 64362306a36Sopenharmony_ci sfp->attr_v4l_minor_number.show = v4l_minor_number_show; 64462306a36Sopenharmony_ci sfp->attr_v4l_minor_number.store = NULL; 64562306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev, 64662306a36Sopenharmony_ci &sfp->attr_v4l_minor_number); 64762306a36Sopenharmony_ci if (ret < 0) { 64862306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 64962306a36Sopenharmony_ci "device_create_file error: %d", 65062306a36Sopenharmony_ci ret); 65162306a36Sopenharmony_ci } else { 65262306a36Sopenharmony_ci sfp->v4l_minor_number_created_ok = !0; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr); 65662306a36Sopenharmony_ci sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number"; 65762306a36Sopenharmony_ci sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO; 65862306a36Sopenharmony_ci sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show; 65962306a36Sopenharmony_ci sfp->attr_v4l_radio_minor_number.store = NULL; 66062306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev, 66162306a36Sopenharmony_ci &sfp->attr_v4l_radio_minor_number); 66262306a36Sopenharmony_ci if (ret < 0) { 66362306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 66462306a36Sopenharmony_ci "device_create_file error: %d", 66562306a36Sopenharmony_ci ret); 66662306a36Sopenharmony_ci } else { 66762306a36Sopenharmony_ci sfp->v4l_radio_minor_number_created_ok = !0; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci sysfs_attr_init(&sfp->attr_unit_number.attr); 67162306a36Sopenharmony_ci sfp->attr_unit_number.attr.name = "unit_number"; 67262306a36Sopenharmony_ci sfp->attr_unit_number.attr.mode = S_IRUGO; 67362306a36Sopenharmony_ci sfp->attr_unit_number.show = unit_number_show; 67462306a36Sopenharmony_ci sfp->attr_unit_number.store = NULL; 67562306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number); 67662306a36Sopenharmony_ci if (ret < 0) { 67762306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 67862306a36Sopenharmony_ci "device_create_file error: %d", 67962306a36Sopenharmony_ci ret); 68062306a36Sopenharmony_ci } else { 68162306a36Sopenharmony_ci sfp->unit_number_created_ok = !0; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci sysfs_attr_init(&sfp->attr_bus_info.attr); 68562306a36Sopenharmony_ci sfp->attr_bus_info.attr.name = "bus_info_str"; 68662306a36Sopenharmony_ci sfp->attr_bus_info.attr.mode = S_IRUGO; 68762306a36Sopenharmony_ci sfp->attr_bus_info.show = bus_info_show; 68862306a36Sopenharmony_ci sfp->attr_bus_info.store = NULL; 68962306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev, 69062306a36Sopenharmony_ci &sfp->attr_bus_info); 69162306a36Sopenharmony_ci if (ret < 0) { 69262306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 69362306a36Sopenharmony_ci "device_create_file error: %d", 69462306a36Sopenharmony_ci ret); 69562306a36Sopenharmony_ci } else { 69662306a36Sopenharmony_ci sfp->bus_info_created_ok = !0; 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci sysfs_attr_init(&sfp->attr_hdw_name.attr); 70062306a36Sopenharmony_ci sfp->attr_hdw_name.attr.name = "device_hardware_type"; 70162306a36Sopenharmony_ci sfp->attr_hdw_name.attr.mode = S_IRUGO; 70262306a36Sopenharmony_ci sfp->attr_hdw_name.show = hdw_name_show; 70362306a36Sopenharmony_ci sfp->attr_hdw_name.store = NULL; 70462306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev, 70562306a36Sopenharmony_ci &sfp->attr_hdw_name); 70662306a36Sopenharmony_ci if (ret < 0) { 70762306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 70862306a36Sopenharmony_ci "device_create_file error: %d", 70962306a36Sopenharmony_ci ret); 71062306a36Sopenharmony_ci } else { 71162306a36Sopenharmony_ci sfp->hdw_name_created_ok = !0; 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci sysfs_attr_init(&sfp->attr_hdw_desc.attr); 71562306a36Sopenharmony_ci sfp->attr_hdw_desc.attr.name = "device_hardware_description"; 71662306a36Sopenharmony_ci sfp->attr_hdw_desc.attr.mode = S_IRUGO; 71762306a36Sopenharmony_ci sfp->attr_hdw_desc.show = hdw_desc_show; 71862306a36Sopenharmony_ci sfp->attr_hdw_desc.store = NULL; 71962306a36Sopenharmony_ci ret = device_create_file(sfp->class_dev, 72062306a36Sopenharmony_ci &sfp->attr_hdw_desc); 72162306a36Sopenharmony_ci if (ret < 0) { 72262306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_ERROR_LEGS, 72362306a36Sopenharmony_ci "device_create_file error: %d", 72462306a36Sopenharmony_ci ret); 72562306a36Sopenharmony_ci } else { 72662306a36Sopenharmony_ci sfp->hdw_desc_created_ok = !0; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci pvr2_sysfs_add_controls(sfp); 73062306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 73162306a36Sopenharmony_ci pvr2_sysfs_add_debugifc(sfp); 73262306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_cistatic void pvr2_sysfs_internal_check(struct pvr2_channel *chp) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 73962306a36Sopenharmony_ci sfp = container_of(chp,struct pvr2_sysfs,channel); 74062306a36Sopenharmony_ci if (!sfp->channel.mc_head->disconnect_flag) return; 74162306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp); 74262306a36Sopenharmony_ci class_dev_destroy(sfp); 74362306a36Sopenharmony_ci pvr2_channel_done(&sfp->channel); 74462306a36Sopenharmony_ci kfree(sfp); 74562306a36Sopenharmony_ci} 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_civoid pvr2_sysfs_create(struct pvr2_context *mp) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 75162306a36Sopenharmony_ci sfp = kzalloc(sizeof(*sfp),GFP_KERNEL); 75262306a36Sopenharmony_ci if (!sfp) 75362306a36Sopenharmony_ci return; 75462306a36Sopenharmony_ci pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp); 75562306a36Sopenharmony_ci pvr2_channel_init(&sfp->channel,mp); 75662306a36Sopenharmony_ci sfp->channel.check_func = pvr2_sysfs_internal_check; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci class_dev_create(sfp); 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_civoid pvr2_sysfs_class_create(void) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci if (class_register(&pvr2_class)) 76562306a36Sopenharmony_ci pvr2_sysfs_trace("Registration failed for pvr2_sysfs_class"); 76662306a36Sopenharmony_ci} 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_civoid pvr2_sysfs_class_destroy(void) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci class_unregister(&pvr2_class); 77262306a36Sopenharmony_ci} 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC 77662306a36Sopenharmony_cistatic ssize_t debuginfo_show(struct device *class_dev, 77762306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 77862306a36Sopenharmony_ci{ 77962306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 78062306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 78162306a36Sopenharmony_ci if (!sfp) return -EINVAL; 78262306a36Sopenharmony_ci pvr2_hdw_trigger_module_log(sfp->channel.hdw); 78362306a36Sopenharmony_ci return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cistatic ssize_t debugcmd_show(struct device *class_dev, 78862306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 79162306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 79262306a36Sopenharmony_ci if (!sfp) return -EINVAL; 79362306a36Sopenharmony_ci return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic ssize_t debugcmd_store(struct device *class_dev, 79862306a36Sopenharmony_ci struct device_attribute *attr, 79962306a36Sopenharmony_ci const char *buf, size_t count) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci struct pvr2_sysfs *sfp; 80262306a36Sopenharmony_ci int ret; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci sfp = dev_get_drvdata(class_dev); 80562306a36Sopenharmony_ci if (!sfp) return -EINVAL; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); 80862306a36Sopenharmony_ci if (ret < 0) return ret; 80962306a36Sopenharmony_ci return count; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ 812