V4L/DVB (7939): pvrusb2: Remove sysfs interface hackery

Back in the early days of the pvrusb2 driver, the kernel class
mechanism in use for the sysfs interface had no means to pass
per-attribute information to the show / store functions.  This forced
me to implement a horrible ugly thunking mechanism (i.e. infer the
missing data through the use of dedicated cookie cutter bounce
functions).  However now we're using a better mechanism which also
passes enough additional information to the show / store functions
that we no longer need the hack.  So eliminate all the crap.  Yay!

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 34a234c..46a8c39 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -70,6 +70,7 @@
 	struct device_attribute attr_val;
 	struct device_attribute attr_custom;
 	struct pvr2_ctrl *cptr;
+	int ctl_id;
 	struct pvr2_sysfs *chptr;
 	struct pvr2_sysfs_ctl_item *item_next;
 	struct attribute *attr_gen[7];
@@ -82,38 +83,29 @@
 	struct class class;
 };
 
-static ssize_t show_name(int id,struct device *class_dev,char *buf)
+static ssize_t show_name(struct device *class_dev,
+			 struct device_attribute *attr,
+			 char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	const char *name;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	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);
-
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
+	name = pvr2_ctrl_get_desc(cip->cptr);
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
+			 cip->chptr, cip->ctl_id, name);
 	if (!name) return -EINVAL;
-
-	return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", name);
 }
 
-static ssize_t show_type(int id,struct device *class_dev,char *buf)
+static ssize_t show_type(struct device *class_dev,
+			 struct device_attribute *attr,
+			 char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	const char *name;
 	enum pvr2_ctl_type tp;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_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);
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
+	tp = pvr2_ctrl_get_type(cip->cptr);
 	switch (tp) {
 	case pvr2_ctl_int: name = "integer"; break;
 	case pvr2_ctl_enum: name = "enum"; break;
@@ -121,403 +113,178 @@
 	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);
-
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
+			 cip->chptr, cip->ctl_id, name);
 	if (!name) return -EINVAL;
-
-	return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", name);
 }
 
-static ssize_t show_min(int id,struct device *class_dev,char *buf)
+static ssize_t show_min(struct device *class_dev,
+			struct device_attribute *attr,
+			char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	long val;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	if (!cptr) return -EINVAL;
-	val = pvr2_ctrl_get_min(cptr);
-
-	pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val);
-
-	return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
+	val = pvr2_ctrl_get_min(cip->cptr);
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
+			 cip->chptr, cip->ctl_id, val);
+	return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
 }
 
-static ssize_t show_max(int id,struct device *class_dev,char *buf)
+static ssize_t show_max(struct device *class_dev,
+			struct device_attribute *attr,
+			char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	long val;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	if (!cptr) return -EINVAL;
-	val = pvr2_ctrl_get_max(cptr);
-
-	pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val);
-
-	return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
+	val = pvr2_ctrl_get_max(cip->cptr);
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
+			 cip->chptr, cip->ctl_id, val);
+	return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
 }
 
-static ssize_t show_val_norm(int id,struct device *class_dev,char *buf)
+static ssize_t show_val_norm(struct device *class_dev,
+			     struct device_attribute *attr,
+			     char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
-	int val,ret;
+	struct pvr2_sysfs_ctl_item *cip;
+	int val;
+	int ret;
 	unsigned int cnt = 0;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	if (!cptr) return -EINVAL;
-
-	ret = pvr2_ctrl_get_value(cptr,&val);
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
+	ret = pvr2_ctrl_get_value(cip->cptr, &val);
 	if (ret < 0) return ret;
-
-	ret = pvr2_ctrl_value_to_sym(cptr,~0,val,
-				     buf,PAGE_SIZE-1,&cnt);
-
+	ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
+				     buf, PAGE_SIZE - 1, &cnt);
 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
-			 sfp,id,cnt,buf,val);
+			 cip->chptr, cip->ctl_id, cnt, buf, val);
 	buf[cnt] = '\n';
 	return cnt+1;
 }
 
-static ssize_t show_val_custom(int id,struct device *class_dev,char *buf)
+static ssize_t show_val_custom(struct device *class_dev,
+			       struct device_attribute *attr,
+			       char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
-	int val,ret;
+	struct pvr2_sysfs_ctl_item *cip;
+	int val;
+	int ret;
 	unsigned int cnt = 0;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	if (!cptr) return -EINVAL;
-
-	ret = pvr2_ctrl_get_value(cptr,&val);
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
+	ret = pvr2_ctrl_get_value(cip->cptr, &val);
 	if (ret < 0) return ret;
-
-	ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val,
-					    buf,PAGE_SIZE-1,&cnt);
-
+	ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
+					    buf, PAGE_SIZE - 1, &cnt);
 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
-			 sfp,id,cnt,buf,val);
+			 cip->chptr, cip->ctl_id, cnt, buf, val);
 	buf[cnt] = '\n';
 	return cnt+1;
 }
 
-static ssize_t show_enum(int id,struct device *class_dev,char *buf)
+static ssize_t show_enum(struct device *class_dev,
+			 struct device_attribute *attr,
+			 char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	long val;
-	unsigned int bcnt,ccnt,ecnt;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	if (!cptr) return -EINVAL;
-	ecnt = pvr2_ctrl_get_cnt(cptr);
+	unsigned int bcnt, ccnt, ecnt;
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
+	ecnt = pvr2_ctrl_get_cnt(cip->cptr);
 	bcnt = 0;
 	for (val = 0; val < ecnt; val++) {
-		pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+		pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
+				      PAGE_SIZE - bcnt, &ccnt);
 		if (!ccnt) continue;
 		bcnt += ccnt;
 		if (bcnt >= PAGE_SIZE) break;
 		buf[bcnt] = '\n';
 		bcnt++;
 	}
-	pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id);
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
+			 cip->chptr, cip->ctl_id);
 	return bcnt;
 }
 
-static ssize_t show_bits(int id,struct device *class_dev,char *buf)
+static ssize_t show_bits(struct device *class_dev,
+			 struct device_attribute *attr,
+			 char *buf)
 {
-	struct pvr2_ctrl *cptr;
-	struct pvr2_sysfs *sfp;
-	int valid_bits,msk;
-	unsigned int bcnt,ccnt;
-
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
-	if (!sfp) return -EINVAL;
-	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
-	if (!cptr) return -EINVAL;
-	valid_bits = pvr2_ctrl_get_mask(cptr);
+	struct pvr2_sysfs_ctl_item *cip;
+	int valid_bits, msk;
+	unsigned int bcnt, ccnt;
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
+	valid_bits = pvr2_ctrl_get_mask(cip->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);
+		pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
+				      PAGE_SIZE - bcnt, &ccnt);
 		bcnt += ccnt;
 		if (bcnt >= PAGE_SIZE) break;
 		buf[bcnt] = '\n';
 		bcnt++;
 	}
-	pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id);
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
+			 cip->chptr, cip->ctl_id);
 	return bcnt;
 }
 
-static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,
+static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
 			 const char *buf,unsigned int count)
 {
-	struct pvr2_ctrl *cptr;
 	int ret;
 	int mask,val;
-
-	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);
+		ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
+						    &mask, &val);
 	} else {
-		ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val);
+		ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
+					     &mask, &val);
 	}
 	if (ret < 0) return ret;
-	ret = pvr2_ctrl_set_mask_value(cptr,mask,val);
-	pvr2_hdw_commit_ctl(sfp->channel.hdw);
+	ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
+	pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
 	return ret;
 }
 
-static ssize_t store_val_norm(int id,struct device *class_dev,
-			     const char *buf,size_t count)
+static ssize_t store_val_norm(struct device *class_dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
 {
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	int ret;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
 	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
-			 sfp,id,(int)count,buf);
-	ret = store_val_any(id,0,sfp,buf,count);
+			 cip->chptr, cip->ctl_id, (int)count, buf);
+	ret = store_val_any(cip, 0, buf, count);
 	if (!ret) ret = count;
 	return ret;
 }
 
-static ssize_t store_val_custom(int id,struct device *class_dev,
-				const char *buf,size_t count)
+static ssize_t store_val_custom(struct device *class_dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
 {
-	struct pvr2_sysfs *sfp;
+	struct pvr2_sysfs_ctl_item *cip;
 	int ret;
-	sfp = (struct pvr2_sysfs *)class_dev->driver_data;
+	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
 	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
-			 sfp,id,(int)count,buf);
-	ret = store_val_any(id,1,sfp,buf,count);
+			 cip->chptr, cip->ctl_id, (int)count, buf);
+	ret = store_val_any(cip, 1, buf, count);
 	if (!ret) ret = count;
 	return ret;
 }
 
-/*
-  Mike Isely <isely@pobox.com> 30-April-2005
-
-  This next batch of horrible preprocessor hackery is needed because the
-  kernel's device_attribute mechanism fails to pass the actual
-  attribute through to the show / store functions, which means we have no
-  way to package up any attribute-specific parameters, like for example the
-  control id.  So we work around this brain-damage by encoding the control
-  id into the show / store functions themselves and pick the function based
-  on the control id we're setting up.  These macros try to ease the pain.
-  Yuck.
-*/
-
-#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
-static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
-struct device_attribute *attr, char *buf) \
-{ return sf_name(ctl_id,class_dev,buf); }
-
-#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
-static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
-struct device_attribute *attr, const char *buf, size_t count) \
-{ return sf_name(ctl_id,class_dev,buf,count); }
-
-#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) \
-CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
-CREATE_SHOW_INSTANCE(show_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)
-CREATE_BATCH(2)
-CREATE_BATCH(3)
-CREATE_BATCH(4)
-CREATE_BATCH(5)
-CREATE_BATCH(6)
-CREATE_BATCH(7)
-CREATE_BATCH(8)
-CREATE_BATCH(9)
-CREATE_BATCH(10)
-CREATE_BATCH(11)
-CREATE_BATCH(12)
-CREATE_BATCH(13)
-CREATE_BATCH(14)
-CREATE_BATCH(15)
-CREATE_BATCH(16)
-CREATE_BATCH(17)
-CREATE_BATCH(18)
-CREATE_BATCH(19)
-CREATE_BATCH(20)
-CREATE_BATCH(21)
-CREATE_BATCH(22)
-CREATE_BATCH(23)
-CREATE_BATCH(24)
-CREATE_BATCH(25)
-CREATE_BATCH(26)
-CREATE_BATCH(27)
-CREATE_BATCH(28)
-CREATE_BATCH(29)
-CREATE_BATCH(30)
-CREATE_BATCH(31)
-CREATE_BATCH(32)
-CREATE_BATCH(33)
-CREATE_BATCH(34)
-CREATE_BATCH(35)
-CREATE_BATCH(36)
-CREATE_BATCH(37)
-CREATE_BATCH(38)
-CREATE_BATCH(39)
-CREATE_BATCH(40)
-CREATE_BATCH(41)
-CREATE_BATCH(42)
-CREATE_BATCH(43)
-CREATE_BATCH(44)
-CREATE_BATCH(45)
-CREATE_BATCH(46)
-CREATE_BATCH(47)
-CREATE_BATCH(48)
-CREATE_BATCH(49)
-CREATE_BATCH(50)
-CREATE_BATCH(51)
-CREATE_BATCH(52)
-CREATE_BATCH(53)
-CREATE_BATCH(54)
-CREATE_BATCH(55)
-CREATE_BATCH(56)
-CREATE_BATCH(57)
-CREATE_BATCH(58)
-CREATE_BATCH(59)
-
-struct pvr2_sysfs_func_set {
-	ssize_t (*show_name)(struct device *,
-			     struct device_attribute *attr, char *);
-	ssize_t (*show_type)(struct device *,
-			     struct device_attribute *attr, char *);
-	ssize_t (*show_min)(struct device *,
-			    struct device_attribute *attr, char *);
-	ssize_t (*show_max)(struct device *,
-			    struct device_attribute *attr, char *);
-	ssize_t (*show_enum)(struct device *,
-			     struct device_attribute *attr, char *);
-	ssize_t (*show_bits)(struct device *,
-			     struct device_attribute *attr, char *);
-	ssize_t (*show_val_norm)(struct device *,
-				 struct device_attribute *attr, char *);
-	ssize_t (*store_val_norm)(struct device *,
-				  struct device_attribute *attr,
-				  const char *,size_t);
-	ssize_t (*show_val_custom)(struct device *,
-				   struct device_attribute *attr, char *);
-	ssize_t (*store_val_custom)(struct device *,
-				    struct device_attribute *attr,
-				    const char *,size_t);
-};
-
-#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, \
-    .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[] = {
-	INIT_BATCH(0),
-	INIT_BATCH(1),
-	INIT_BATCH(2),
-	INIT_BATCH(3),
-	INIT_BATCH(4),
-	INIT_BATCH(5),
-	INIT_BATCH(6),
-	INIT_BATCH(7),
-	INIT_BATCH(8),
-	INIT_BATCH(9),
-	INIT_BATCH(10),
-	INIT_BATCH(11),
-	INIT_BATCH(12),
-	INIT_BATCH(13),
-	INIT_BATCH(14),
-	INIT_BATCH(15),
-	INIT_BATCH(16),
-	INIT_BATCH(17),
-	INIT_BATCH(18),
-	INIT_BATCH(19),
-	INIT_BATCH(20),
-	INIT_BATCH(21),
-	INIT_BATCH(22),
-	INIT_BATCH(23),
-	INIT_BATCH(24),
-	INIT_BATCH(25),
-	INIT_BATCH(26),
-	INIT_BATCH(27),
-	INIT_BATCH(28),
-	INIT_BATCH(29),
-	INIT_BATCH(30),
-	INIT_BATCH(31),
-	INIT_BATCH(32),
-	INIT_BATCH(33),
-	INIT_BATCH(34),
-	INIT_BATCH(35),
-	INIT_BATCH(36),
-	INIT_BATCH(37),
-	INIT_BATCH(38),
-	INIT_BATCH(39),
-	INIT_BATCH(40),
-	INIT_BATCH(41),
-	INIT_BATCH(42),
-	INIT_BATCH(43),
-	INIT_BATCH(44),
-	INIT_BATCH(45),
-	INIT_BATCH(46),
-	INIT_BATCH(47),
-	INIT_BATCH(48),
-	INIT_BATCH(49),
-	INIT_BATCH(50),
-	INIT_BATCH(51),
-	INIT_BATCH(52),
-	INIT_BATCH(53),
-	INIT_BATCH(54),
-	INIT_BATCH(55),
-	INIT_BATCH(56),
-	INIT_BATCH(57),
-	INIT_BATCH(58),
-	INIT_BATCH(59),
-};
-
-
 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,acnt;
 	int ret;
 
-	if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) {
-		return;
-	}
-
-	fp = funcs + ctl_id;
 	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
 	if (!cptr) return;
 
@@ -526,6 +293,7 @@
 	pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
 
 	cip->cptr = cptr;
+	cip->ctl_id = ctl_id;
 
 	cip->chptr = sfp;
 	cip->item_next = NULL;
@@ -538,19 +306,19 @@
 
 	cip->attr_name.attr.name = "name";
 	cip->attr_name.attr.mode = S_IRUGO;
-	cip->attr_name.show = fp->show_name;
+	cip->attr_name.show = show_name;
 
 	cip->attr_type.attr.name = "type";
 	cip->attr_type.attr.mode = S_IRUGO;
-	cip->attr_type.show = fp->show_type;
+	cip->attr_type.show = show_type;
 
 	cip->attr_min.attr.name = "min_val";
 	cip->attr_min.attr.mode = S_IRUGO;
-	cip->attr_min.show = fp->show_min;
+	cip->attr_min.show = show_min;
 
 	cip->attr_max.attr.name = "max_val";
 	cip->attr_max.attr.mode = S_IRUGO;
-	cip->attr_max.show = fp->show_max;
+	cip->attr_max.show = show_max;
 
 	cip->attr_val.attr.name = "cur_val";
 	cip->attr_val.attr.mode = S_IRUGO;
@@ -560,11 +328,11 @@
 
 	cip->attr_enum.attr.name = "enum_val";
 	cip->attr_enum.attr.mode = S_IRUGO;
-	cip->attr_enum.show = fp->show_enum;
+	cip->attr_enum.show = show_enum;
 
 	cip->attr_bits.attr.name = "bit_val";
 	cip->attr_bits.attr.mode = S_IRUGO;
-	cip->attr_bits.show = fp->show_bits;
+	cip->attr_bits.show = show_bits;
 
 	if (pvr2_ctrl_is_writable(cptr)) {
 		cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
@@ -575,12 +343,12 @@
 	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;
+	cip->attr_val.show = show_val_norm;
+	cip->attr_val.store = 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;
+		cip->attr_custom.show = show_val_custom;
+		cip->attr_custom.store = store_val_custom;
 	}
 	switch (pvr2_ctrl_get_type(cptr)) {
 	case pvr2_ctl_enum: