12504ba9fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20c0d06caSMauro Carvalho Chehab /*
30c0d06caSMauro Carvalho Chehab  *
40c0d06caSMauro Carvalho Chehab  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
50c0d06caSMauro Carvalho Chehab  */
60c0d06caSMauro Carvalho Chehab 
70c0d06caSMauro Carvalho Chehab #include <linux/string.h>
80c0d06caSMauro Carvalho Chehab #include <linux/slab.h>
90c0d06caSMauro Carvalho Chehab #include "pvrusb2-sysfs.h"
100c0d06caSMauro Carvalho Chehab #include "pvrusb2-hdw.h"
110c0d06caSMauro Carvalho Chehab #include "pvrusb2-debug.h"
120c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
130c0d06caSMauro Carvalho Chehab #include "pvrusb2-debugifc.h"
140c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
150c0d06caSMauro Carvalho Chehab 
160c0d06caSMauro Carvalho Chehab #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
170c0d06caSMauro Carvalho Chehab 
180c0d06caSMauro Carvalho Chehab struct pvr2_sysfs {
190c0d06caSMauro Carvalho Chehab 	struct pvr2_channel channel;
200c0d06caSMauro Carvalho Chehab 	struct device *class_dev;
210c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
220c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_debugifc *debugifc;
230c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
240c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *item_first;
250c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *item_last;
260c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_v4l_minor_number;
270c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_v4l_radio_minor_number;
280c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_unit_number;
290c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_bus_info;
300c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_hdw_name;
310c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_hdw_desc;
320c0d06caSMauro Carvalho Chehab 	int v4l_minor_number_created_ok;
330c0d06caSMauro Carvalho Chehab 	int v4l_radio_minor_number_created_ok;
340c0d06caSMauro Carvalho Chehab 	int unit_number_created_ok;
350c0d06caSMauro Carvalho Chehab 	int bus_info_created_ok;
360c0d06caSMauro Carvalho Chehab 	int hdw_name_created_ok;
370c0d06caSMauro Carvalho Chehab 	int hdw_desc_created_ok;
380c0d06caSMauro Carvalho Chehab };
390c0d06caSMauro Carvalho Chehab 
400c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
410c0d06caSMauro Carvalho Chehab struct pvr2_sysfs_debugifc {
420c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_debugcmd;
430c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_debuginfo;
440c0d06caSMauro Carvalho Chehab 	int debugcmd_created_ok;
450c0d06caSMauro Carvalho Chehab 	int debuginfo_created_ok;
460c0d06caSMauro Carvalho Chehab };
470c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
480c0d06caSMauro Carvalho Chehab 
490c0d06caSMauro Carvalho Chehab struct pvr2_sysfs_ctl_item {
500c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_name;
510c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_type;
520c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_min;
530c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_max;
540c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_def;
550c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_enum;
560c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_bits;
570c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_val;
580c0d06caSMauro Carvalho Chehab 	struct device_attribute attr_custom;
590c0d06caSMauro Carvalho Chehab 	struct pvr2_ctrl *cptr;
600c0d06caSMauro Carvalho Chehab 	int ctl_id;
610c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *chptr;
620c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *item_next;
630c0d06caSMauro Carvalho Chehab 	struct attribute *attr_gen[8];
640c0d06caSMauro Carvalho Chehab 	struct attribute_group grp;
650c0d06caSMauro Carvalho Chehab 	int created_ok;
660c0d06caSMauro Carvalho Chehab 	char name[80];
670c0d06caSMauro Carvalho Chehab };
680c0d06caSMauro Carvalho Chehab 
show_name(struct device * class_dev,struct device_attribute * attr,char * buf)690c0d06caSMauro Carvalho Chehab static ssize_t show_name(struct device *class_dev,
700c0d06caSMauro Carvalho Chehab 			 struct device_attribute *attr,
710c0d06caSMauro Carvalho Chehab 			 char *buf)
720c0d06caSMauro Carvalho Chehab {
730c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
740c0d06caSMauro Carvalho Chehab 	const char *name;
750c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
760c0d06caSMauro Carvalho Chehab 	name = pvr2_ctrl_get_desc(cip->cptr);
770c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
780c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, name);
790c0d06caSMauro Carvalho Chehab 	if (!name) return -EINVAL;
80*13e6756bSye xingchen 	return sysfs_emit(buf, "%s\n", name);
810c0d06caSMauro Carvalho Chehab }
820c0d06caSMauro Carvalho Chehab 
show_type(struct device * class_dev,struct device_attribute * attr,char * buf)830c0d06caSMauro Carvalho Chehab static ssize_t show_type(struct device *class_dev,
840c0d06caSMauro Carvalho Chehab 			 struct device_attribute *attr,
850c0d06caSMauro Carvalho Chehab 			 char *buf)
860c0d06caSMauro Carvalho Chehab {
870c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
880c0d06caSMauro Carvalho Chehab 	const char *name;
890c0d06caSMauro Carvalho Chehab 	enum pvr2_ctl_type tp;
900c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
910c0d06caSMauro Carvalho Chehab 	tp = pvr2_ctrl_get_type(cip->cptr);
920c0d06caSMauro Carvalho Chehab 	switch (tp) {
930c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_int: name = "integer"; break;
940c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_enum: name = "enum"; break;
950c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_bitmask: name = "bitmask"; break;
960c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_bool: name = "boolean"; break;
970c0d06caSMauro Carvalho Chehab 	default: name = "?"; break;
980c0d06caSMauro Carvalho Chehab 	}
990c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
1000c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, name);
101*13e6756bSye xingchen 	return sysfs_emit(buf, "%s\n", name);
1020c0d06caSMauro Carvalho Chehab }
1030c0d06caSMauro Carvalho Chehab 
show_min(struct device * class_dev,struct device_attribute * attr,char * buf)1040c0d06caSMauro Carvalho Chehab static ssize_t show_min(struct device *class_dev,
1050c0d06caSMauro Carvalho Chehab 			struct device_attribute *attr,
1060c0d06caSMauro Carvalho Chehab 			char *buf)
1070c0d06caSMauro Carvalho Chehab {
1080c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
1090c0d06caSMauro Carvalho Chehab 	long val;
1100c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
1110c0d06caSMauro Carvalho Chehab 	val = pvr2_ctrl_get_min(cip->cptr);
1120c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
1130c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, val);
114*13e6756bSye xingchen 	return sysfs_emit(buf, "%ld\n", val);
1150c0d06caSMauro Carvalho Chehab }
1160c0d06caSMauro Carvalho Chehab 
show_max(struct device * class_dev,struct device_attribute * attr,char * buf)1170c0d06caSMauro Carvalho Chehab static ssize_t show_max(struct device *class_dev,
1180c0d06caSMauro Carvalho Chehab 			struct device_attribute *attr,
1190c0d06caSMauro Carvalho Chehab 			char *buf)
1200c0d06caSMauro Carvalho Chehab {
1210c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
1220c0d06caSMauro Carvalho Chehab 	long val;
1230c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
1240c0d06caSMauro Carvalho Chehab 	val = pvr2_ctrl_get_max(cip->cptr);
1250c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
1260c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, val);
127*13e6756bSye xingchen 	return sysfs_emit(buf, "%ld\n", val);
1280c0d06caSMauro Carvalho Chehab }
1290c0d06caSMauro Carvalho Chehab 
show_def(struct device * class_dev,struct device_attribute * attr,char * buf)1300c0d06caSMauro Carvalho Chehab static ssize_t show_def(struct device *class_dev,
1310c0d06caSMauro Carvalho Chehab 			struct device_attribute *attr,
1320c0d06caSMauro Carvalho Chehab 			char *buf)
1330c0d06caSMauro Carvalho Chehab {
1340c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
1350c0d06caSMauro Carvalho Chehab 	int val;
1360c0d06caSMauro Carvalho Chehab 	int ret;
1370c0d06caSMauro Carvalho Chehab 	unsigned int cnt = 0;
1380c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
1390c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_get_def(cip->cptr, &val);
1400c0d06caSMauro Carvalho Chehab 	if (ret < 0) return ret;
1410c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
1420c0d06caSMauro Carvalho Chehab 				     buf, PAGE_SIZE - 1, &cnt);
1430c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)",
1440c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, cnt, buf, val);
1450c0d06caSMauro Carvalho Chehab 	buf[cnt] = '\n';
1460c0d06caSMauro Carvalho Chehab 	return cnt + 1;
1470c0d06caSMauro Carvalho Chehab }
1480c0d06caSMauro Carvalho Chehab 
show_val_norm(struct device * class_dev,struct device_attribute * attr,char * buf)1490c0d06caSMauro Carvalho Chehab static ssize_t show_val_norm(struct device *class_dev,
1500c0d06caSMauro Carvalho Chehab 			     struct device_attribute *attr,
1510c0d06caSMauro Carvalho Chehab 			     char *buf)
1520c0d06caSMauro Carvalho Chehab {
1530c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
1540c0d06caSMauro Carvalho Chehab 	int val;
1550c0d06caSMauro Carvalho Chehab 	int ret;
1560c0d06caSMauro Carvalho Chehab 	unsigned int cnt = 0;
1570c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
1580c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_get_value(cip->cptr, &val);
1590c0d06caSMauro Carvalho Chehab 	if (ret < 0) return ret;
1600c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
1610c0d06caSMauro Carvalho Chehab 				     buf, PAGE_SIZE - 1, &cnt);
1620c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
1630c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, cnt, buf, val);
1640c0d06caSMauro Carvalho Chehab 	buf[cnt] = '\n';
1650c0d06caSMauro Carvalho Chehab 	return cnt+1;
1660c0d06caSMauro Carvalho Chehab }
1670c0d06caSMauro Carvalho Chehab 
show_val_custom(struct device * class_dev,struct device_attribute * attr,char * buf)1680c0d06caSMauro Carvalho Chehab static ssize_t show_val_custom(struct device *class_dev,
1690c0d06caSMauro Carvalho Chehab 			       struct device_attribute *attr,
1700c0d06caSMauro Carvalho Chehab 			       char *buf)
1710c0d06caSMauro Carvalho Chehab {
1720c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
1730c0d06caSMauro Carvalho Chehab 	int val;
1740c0d06caSMauro Carvalho Chehab 	int ret;
1750c0d06caSMauro Carvalho Chehab 	unsigned int cnt = 0;
1760c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
1770c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_get_value(cip->cptr, &val);
1780c0d06caSMauro Carvalho Chehab 	if (ret < 0) return ret;
1790c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
1800c0d06caSMauro Carvalho Chehab 					    buf, PAGE_SIZE - 1, &cnt);
1810c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
1820c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, cnt, buf, val);
1830c0d06caSMauro Carvalho Chehab 	buf[cnt] = '\n';
1840c0d06caSMauro Carvalho Chehab 	return cnt+1;
1850c0d06caSMauro Carvalho Chehab }
1860c0d06caSMauro Carvalho Chehab 
show_enum(struct device * class_dev,struct device_attribute * attr,char * buf)1870c0d06caSMauro Carvalho Chehab static ssize_t show_enum(struct device *class_dev,
1880c0d06caSMauro Carvalho Chehab 			 struct device_attribute *attr,
1890c0d06caSMauro Carvalho Chehab 			 char *buf)
1900c0d06caSMauro Carvalho Chehab {
1910c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
1920c0d06caSMauro Carvalho Chehab 	long val;
1930c0d06caSMauro Carvalho Chehab 	unsigned int bcnt, ccnt, ecnt;
1940c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
1950c0d06caSMauro Carvalho Chehab 	ecnt = pvr2_ctrl_get_cnt(cip->cptr);
1960c0d06caSMauro Carvalho Chehab 	bcnt = 0;
1970c0d06caSMauro Carvalho Chehab 	for (val = 0; val < ecnt; val++) {
1980c0d06caSMauro Carvalho Chehab 		pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
1990c0d06caSMauro Carvalho Chehab 				      PAGE_SIZE - bcnt, &ccnt);
2000c0d06caSMauro Carvalho Chehab 		if (!ccnt) continue;
2010c0d06caSMauro Carvalho Chehab 		bcnt += ccnt;
2020c0d06caSMauro Carvalho Chehab 		if (bcnt >= PAGE_SIZE) break;
2030c0d06caSMauro Carvalho Chehab 		buf[bcnt] = '\n';
2040c0d06caSMauro Carvalho Chehab 		bcnt++;
2050c0d06caSMauro Carvalho Chehab 	}
2060c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
2070c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id);
2080c0d06caSMauro Carvalho Chehab 	return bcnt;
2090c0d06caSMauro Carvalho Chehab }
2100c0d06caSMauro Carvalho Chehab 
show_bits(struct device * class_dev,struct device_attribute * attr,char * buf)2110c0d06caSMauro Carvalho Chehab static ssize_t show_bits(struct device *class_dev,
2120c0d06caSMauro Carvalho Chehab 			 struct device_attribute *attr,
2130c0d06caSMauro Carvalho Chehab 			 char *buf)
2140c0d06caSMauro Carvalho Chehab {
2150c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
2160c0d06caSMauro Carvalho Chehab 	int valid_bits, msk;
2170c0d06caSMauro Carvalho Chehab 	unsigned int bcnt, ccnt;
2180c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
2190c0d06caSMauro Carvalho Chehab 	valid_bits = pvr2_ctrl_get_mask(cip->cptr);
2200c0d06caSMauro Carvalho Chehab 	bcnt = 0;
2210c0d06caSMauro Carvalho Chehab 	for (msk = 1; valid_bits; msk <<= 1) {
2220c0d06caSMauro Carvalho Chehab 		if (!(msk & valid_bits)) continue;
2230c0d06caSMauro Carvalho Chehab 		valid_bits &= ~msk;
2240c0d06caSMauro Carvalho Chehab 		pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
2250c0d06caSMauro Carvalho Chehab 				      PAGE_SIZE - bcnt, &ccnt);
2260c0d06caSMauro Carvalho Chehab 		bcnt += ccnt;
2270c0d06caSMauro Carvalho Chehab 		if (bcnt >= PAGE_SIZE) break;
2280c0d06caSMauro Carvalho Chehab 		buf[bcnt] = '\n';
2290c0d06caSMauro Carvalho Chehab 		bcnt++;
2300c0d06caSMauro Carvalho Chehab 	}
2310c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
2320c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id);
2330c0d06caSMauro Carvalho Chehab 	return bcnt;
2340c0d06caSMauro Carvalho Chehab }
2350c0d06caSMauro Carvalho Chehab 
store_val_any(struct pvr2_sysfs_ctl_item * cip,int customfl,const char * buf,unsigned int count)2360c0d06caSMauro Carvalho Chehab static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
2370c0d06caSMauro Carvalho Chehab 			 const char *buf,unsigned int count)
2380c0d06caSMauro Carvalho Chehab {
2390c0d06caSMauro Carvalho Chehab 	int ret;
2400c0d06caSMauro Carvalho Chehab 	int mask,val;
2410c0d06caSMauro Carvalho Chehab 	if (customfl) {
2420c0d06caSMauro Carvalho Chehab 		ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
2430c0d06caSMauro Carvalho Chehab 						    &mask, &val);
2440c0d06caSMauro Carvalho Chehab 	} else {
2450c0d06caSMauro Carvalho Chehab 		ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
2460c0d06caSMauro Carvalho Chehab 					     &mask, &val);
2470c0d06caSMauro Carvalho Chehab 	}
2480c0d06caSMauro Carvalho Chehab 	if (ret < 0) return ret;
2490c0d06caSMauro Carvalho Chehab 	ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
2500c0d06caSMauro Carvalho Chehab 	pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
2510c0d06caSMauro Carvalho Chehab 	return ret;
2520c0d06caSMauro Carvalho Chehab }
2530c0d06caSMauro Carvalho Chehab 
store_val_norm(struct device * class_dev,struct device_attribute * attr,const char * buf,size_t count)2540c0d06caSMauro Carvalho Chehab static ssize_t store_val_norm(struct device *class_dev,
2550c0d06caSMauro Carvalho Chehab 			      struct device_attribute *attr,
2560c0d06caSMauro Carvalho Chehab 			      const char *buf, size_t count)
2570c0d06caSMauro Carvalho Chehab {
2580c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
2590c0d06caSMauro Carvalho Chehab 	int ret;
2600c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
2610c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
2620c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, (int)count, buf);
2630c0d06caSMauro Carvalho Chehab 	ret = store_val_any(cip, 0, buf, count);
2640c0d06caSMauro Carvalho Chehab 	if (!ret) ret = count;
2650c0d06caSMauro Carvalho Chehab 	return ret;
2660c0d06caSMauro Carvalho Chehab }
2670c0d06caSMauro Carvalho Chehab 
store_val_custom(struct device * class_dev,struct device_attribute * attr,const char * buf,size_t count)2680c0d06caSMauro Carvalho Chehab static ssize_t store_val_custom(struct device *class_dev,
2690c0d06caSMauro Carvalho Chehab 				struct device_attribute *attr,
2700c0d06caSMauro Carvalho Chehab 				const char *buf, size_t count)
2710c0d06caSMauro Carvalho Chehab {
2720c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
2730c0d06caSMauro Carvalho Chehab 	int ret;
2740c0d06caSMauro Carvalho Chehab 	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
2750c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
2760c0d06caSMauro Carvalho Chehab 			 cip->chptr, cip->ctl_id, (int)count, buf);
2770c0d06caSMauro Carvalho Chehab 	ret = store_val_any(cip, 1, buf, count);
2780c0d06caSMauro Carvalho Chehab 	if (!ret) ret = count;
2790c0d06caSMauro Carvalho Chehab 	return ret;
2800c0d06caSMauro Carvalho Chehab }
2810c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_add_control(struct pvr2_sysfs * sfp,int ctl_id)2820c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
2830c0d06caSMauro Carvalho Chehab {
2840c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip;
2850c0d06caSMauro Carvalho Chehab 	struct pvr2_ctrl *cptr;
2860c0d06caSMauro Carvalho Chehab 	unsigned int cnt,acnt;
2870c0d06caSMauro Carvalho Chehab 	int ret;
2880c0d06caSMauro Carvalho Chehab 
2890c0d06caSMauro Carvalho Chehab 	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
2900c0d06caSMauro Carvalho Chehab 	if (!cptr) return;
2910c0d06caSMauro Carvalho Chehab 
2920c0d06caSMauro Carvalho Chehab 	cip = kzalloc(sizeof(*cip),GFP_KERNEL);
2930c0d06caSMauro Carvalho Chehab 	if (!cip) return;
2940c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
2950c0d06caSMauro Carvalho Chehab 
2960c0d06caSMauro Carvalho Chehab 	cip->cptr = cptr;
2970c0d06caSMauro Carvalho Chehab 	cip->ctl_id = ctl_id;
2980c0d06caSMauro Carvalho Chehab 
2990c0d06caSMauro Carvalho Chehab 	cip->chptr = sfp;
3000c0d06caSMauro Carvalho Chehab 	cip->item_next = NULL;
3010c0d06caSMauro Carvalho Chehab 	if (sfp->item_last) {
3020c0d06caSMauro Carvalho Chehab 		sfp->item_last->item_next = cip;
3030c0d06caSMauro Carvalho Chehab 	} else {
3040c0d06caSMauro Carvalho Chehab 		sfp->item_first = cip;
3050c0d06caSMauro Carvalho Chehab 	}
3060c0d06caSMauro Carvalho Chehab 	sfp->item_last = cip;
3070c0d06caSMauro Carvalho Chehab 
3080c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_name.attr);
3090c0d06caSMauro Carvalho Chehab 	cip->attr_name.attr.name = "name";
3100c0d06caSMauro Carvalho Chehab 	cip->attr_name.attr.mode = S_IRUGO;
3110c0d06caSMauro Carvalho Chehab 	cip->attr_name.show = show_name;
3120c0d06caSMauro Carvalho Chehab 
3130c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_type.attr);
3140c0d06caSMauro Carvalho Chehab 	cip->attr_type.attr.name = "type";
3150c0d06caSMauro Carvalho Chehab 	cip->attr_type.attr.mode = S_IRUGO;
3160c0d06caSMauro Carvalho Chehab 	cip->attr_type.show = show_type;
3170c0d06caSMauro Carvalho Chehab 
3180c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_min.attr);
3190c0d06caSMauro Carvalho Chehab 	cip->attr_min.attr.name = "min_val";
3200c0d06caSMauro Carvalho Chehab 	cip->attr_min.attr.mode = S_IRUGO;
3210c0d06caSMauro Carvalho Chehab 	cip->attr_min.show = show_min;
3220c0d06caSMauro Carvalho Chehab 
3230c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_max.attr);
3240c0d06caSMauro Carvalho Chehab 	cip->attr_max.attr.name = "max_val";
3250c0d06caSMauro Carvalho Chehab 	cip->attr_max.attr.mode = S_IRUGO;
3260c0d06caSMauro Carvalho Chehab 	cip->attr_max.show = show_max;
3270c0d06caSMauro Carvalho Chehab 
3280c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_def.attr);
3290c0d06caSMauro Carvalho Chehab 	cip->attr_def.attr.name = "def_val";
3300c0d06caSMauro Carvalho Chehab 	cip->attr_def.attr.mode = S_IRUGO;
3310c0d06caSMauro Carvalho Chehab 	cip->attr_def.show = show_def;
3320c0d06caSMauro Carvalho Chehab 
3330c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_val.attr);
3340c0d06caSMauro Carvalho Chehab 	cip->attr_val.attr.name = "cur_val";
3350c0d06caSMauro Carvalho Chehab 	cip->attr_val.attr.mode = S_IRUGO;
3360c0d06caSMauro Carvalho Chehab 
3370c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_custom.attr);
3380c0d06caSMauro Carvalho Chehab 	cip->attr_custom.attr.name = "custom_val";
3390c0d06caSMauro Carvalho Chehab 	cip->attr_custom.attr.mode = S_IRUGO;
3400c0d06caSMauro Carvalho Chehab 
3410c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_enum.attr);
3420c0d06caSMauro Carvalho Chehab 	cip->attr_enum.attr.name = "enum_val";
3430c0d06caSMauro Carvalho Chehab 	cip->attr_enum.attr.mode = S_IRUGO;
3440c0d06caSMauro Carvalho Chehab 	cip->attr_enum.show = show_enum;
3450c0d06caSMauro Carvalho Chehab 
3460c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&cip->attr_bits.attr);
3470c0d06caSMauro Carvalho Chehab 	cip->attr_bits.attr.name = "bit_val";
3480c0d06caSMauro Carvalho Chehab 	cip->attr_bits.attr.mode = S_IRUGO;
3490c0d06caSMauro Carvalho Chehab 	cip->attr_bits.show = show_bits;
3500c0d06caSMauro Carvalho Chehab 
3510c0d06caSMauro Carvalho Chehab 	if (pvr2_ctrl_is_writable(cptr)) {
3520c0d06caSMauro Carvalho Chehab 		cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
3530c0d06caSMauro Carvalho Chehab 		cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
3540c0d06caSMauro Carvalho Chehab 	}
3550c0d06caSMauro Carvalho Chehab 
3560c0d06caSMauro Carvalho Chehab 	acnt = 0;
3570c0d06caSMauro Carvalho Chehab 	cip->attr_gen[acnt++] = &cip->attr_name.attr;
3580c0d06caSMauro Carvalho Chehab 	cip->attr_gen[acnt++] = &cip->attr_type.attr;
3590c0d06caSMauro Carvalho Chehab 	cip->attr_gen[acnt++] = &cip->attr_val.attr;
3600c0d06caSMauro Carvalho Chehab 	cip->attr_gen[acnt++] = &cip->attr_def.attr;
3610c0d06caSMauro Carvalho Chehab 	cip->attr_val.show = show_val_norm;
3620c0d06caSMauro Carvalho Chehab 	cip->attr_val.store = store_val_norm;
3630c0d06caSMauro Carvalho Chehab 	if (pvr2_ctrl_has_custom_symbols(cptr)) {
3640c0d06caSMauro Carvalho Chehab 		cip->attr_gen[acnt++] = &cip->attr_custom.attr;
3650c0d06caSMauro Carvalho Chehab 		cip->attr_custom.show = show_val_custom;
3660c0d06caSMauro Carvalho Chehab 		cip->attr_custom.store = store_val_custom;
3670c0d06caSMauro Carvalho Chehab 	}
3680c0d06caSMauro Carvalho Chehab 	switch (pvr2_ctrl_get_type(cptr)) {
3690c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_enum:
3700c0d06caSMauro Carvalho Chehab 		// Control is an enumeration
3710c0d06caSMauro Carvalho Chehab 		cip->attr_gen[acnt++] = &cip->attr_enum.attr;
3720c0d06caSMauro Carvalho Chehab 		break;
3730c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_int:
3740c0d06caSMauro Carvalho Chehab 		// Control is an integer
3750c0d06caSMauro Carvalho Chehab 		cip->attr_gen[acnt++] = &cip->attr_min.attr;
3760c0d06caSMauro Carvalho Chehab 		cip->attr_gen[acnt++] = &cip->attr_max.attr;
3770c0d06caSMauro Carvalho Chehab 		break;
3780c0d06caSMauro Carvalho Chehab 	case pvr2_ctl_bitmask:
3790c0d06caSMauro Carvalho Chehab 		// Control is an bitmask
3800c0d06caSMauro Carvalho Chehab 		cip->attr_gen[acnt++] = &cip->attr_bits.attr;
3810c0d06caSMauro Carvalho Chehab 		break;
3820c0d06caSMauro Carvalho Chehab 	default: break;
3830c0d06caSMauro Carvalho Chehab 	}
3840c0d06caSMauro Carvalho Chehab 
3850c0d06caSMauro Carvalho Chehab 	cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
3860c0d06caSMauro Carvalho Chehab 			pvr2_ctrl_get_name(cptr));
3870c0d06caSMauro Carvalho Chehab 	cip->name[cnt] = 0;
3880c0d06caSMauro Carvalho Chehab 	cip->grp.name = cip->name;
3890c0d06caSMauro Carvalho Chehab 	cip->grp.attrs = cip->attr_gen;
3900c0d06caSMauro Carvalho Chehab 
3910c0d06caSMauro Carvalho Chehab 	ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
3920c0d06caSMauro Carvalho Chehab 	if (ret) {
3930c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
3940c0d06caSMauro Carvalho Chehab 			   "sysfs_create_group error: %d",
3950c0d06caSMauro Carvalho Chehab 			   ret);
3960c0d06caSMauro Carvalho Chehab 		return;
3970c0d06caSMauro Carvalho Chehab 	}
3980c0d06caSMauro Carvalho Chehab 	cip->created_ok = !0;
3990c0d06caSMauro Carvalho Chehab }
4000c0d06caSMauro Carvalho Chehab 
4010c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
4020c0d06caSMauro Carvalho Chehab static ssize_t debuginfo_show(struct device *, struct device_attribute *,
4030c0d06caSMauro Carvalho Chehab 			      char *);
4040c0d06caSMauro Carvalho Chehab static ssize_t debugcmd_show(struct device *, struct device_attribute *,
4050c0d06caSMauro Carvalho Chehab 			     char *);
4060c0d06caSMauro Carvalho Chehab static ssize_t debugcmd_store(struct device *, struct device_attribute *,
4070c0d06caSMauro Carvalho Chehab 			      const char *, size_t count);
4080c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_add_debugifc(struct pvr2_sysfs * sfp)4090c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
4100c0d06caSMauro Carvalho Chehab {
4110c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_debugifc *dip;
4120c0d06caSMauro Carvalho Chehab 	int ret;
4130c0d06caSMauro Carvalho Chehab 
4140c0d06caSMauro Carvalho Chehab 	dip = kzalloc(sizeof(*dip),GFP_KERNEL);
4150c0d06caSMauro Carvalho Chehab 	if (!dip) return;
4160c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&dip->attr_debugcmd.attr);
4170c0d06caSMauro Carvalho Chehab 	dip->attr_debugcmd.attr.name = "debugcmd";
4180c0d06caSMauro Carvalho Chehab 	dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
4190c0d06caSMauro Carvalho Chehab 	dip->attr_debugcmd.show = debugcmd_show;
4200c0d06caSMauro Carvalho Chehab 	dip->attr_debugcmd.store = debugcmd_store;
4210c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&dip->attr_debuginfo.attr);
4220c0d06caSMauro Carvalho Chehab 	dip->attr_debuginfo.attr.name = "debuginfo";
4230c0d06caSMauro Carvalho Chehab 	dip->attr_debuginfo.attr.mode = S_IRUGO;
4240c0d06caSMauro Carvalho Chehab 	dip->attr_debuginfo.show = debuginfo_show;
4250c0d06caSMauro Carvalho Chehab 	sfp->debugifc = dip;
4260c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
4270c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
4280c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
4290c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
4300c0d06caSMauro Carvalho Chehab 			   ret);
4310c0d06caSMauro Carvalho Chehab 	} else {
4320c0d06caSMauro Carvalho Chehab 		dip->debugcmd_created_ok = !0;
4330c0d06caSMauro Carvalho Chehab 	}
4340c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
4350c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
4360c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
4370c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
4380c0d06caSMauro Carvalho Chehab 			   ret);
4390c0d06caSMauro Carvalho Chehab 	} else {
4400c0d06caSMauro Carvalho Chehab 		dip->debuginfo_created_ok = !0;
4410c0d06caSMauro Carvalho Chehab 	}
4420c0d06caSMauro Carvalho Chehab }
4430c0d06caSMauro Carvalho Chehab 
4440c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs * sfp)4450c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
4460c0d06caSMauro Carvalho Chehab {
4470c0d06caSMauro Carvalho Chehab 	if (!sfp->debugifc) return;
4480c0d06caSMauro Carvalho Chehab 	if (sfp->debugifc->debuginfo_created_ok) {
4490c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
4500c0d06caSMauro Carvalho Chehab 					 &sfp->debugifc->attr_debuginfo);
4510c0d06caSMauro Carvalho Chehab 	}
4520c0d06caSMauro Carvalho Chehab 	if (sfp->debugifc->debugcmd_created_ok) {
4530c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
4540c0d06caSMauro Carvalho Chehab 					 &sfp->debugifc->attr_debugcmd);
4550c0d06caSMauro Carvalho Chehab 	}
4560c0d06caSMauro Carvalho Chehab 	kfree(sfp->debugifc);
4570c0d06caSMauro Carvalho Chehab 	sfp->debugifc = NULL;
4580c0d06caSMauro Carvalho Chehab }
4590c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
4600c0d06caSMauro Carvalho Chehab 
4610c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_add_controls(struct pvr2_sysfs * sfp)4620c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
4630c0d06caSMauro Carvalho Chehab {
4640c0d06caSMauro Carvalho Chehab 	unsigned int idx,cnt;
4650c0d06caSMauro Carvalho Chehab 	cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
4660c0d06caSMauro Carvalho Chehab 	for (idx = 0; idx < cnt; idx++) {
4670c0d06caSMauro Carvalho Chehab 		pvr2_sysfs_add_control(sfp,idx);
4680c0d06caSMauro Carvalho Chehab 	}
4690c0d06caSMauro Carvalho Chehab }
4700c0d06caSMauro Carvalho Chehab 
4710c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_tear_down_controls(struct pvr2_sysfs * sfp)4720c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
4730c0d06caSMauro Carvalho Chehab {
4740c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs_ctl_item *cip1,*cip2;
4750c0d06caSMauro Carvalho Chehab 	for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
4760c0d06caSMauro Carvalho Chehab 		cip2 = cip1->item_next;
4770c0d06caSMauro Carvalho Chehab 		if (cip1->created_ok) {
4780c0d06caSMauro Carvalho Chehab 			sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
4790c0d06caSMauro Carvalho Chehab 		}
4800c0d06caSMauro Carvalho Chehab 		pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
4810c0d06caSMauro Carvalho Chehab 		kfree(cip1);
4820c0d06caSMauro Carvalho Chehab 	}
4830c0d06caSMauro Carvalho Chehab }
4840c0d06caSMauro Carvalho Chehab 
4850c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_release(struct device * class_dev)4860c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_release(struct device *class_dev)
4870c0d06caSMauro Carvalho Chehab {
4880c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
4890c0d06caSMauro Carvalho Chehab 	kfree(class_dev);
4900c0d06caSMauro Carvalho Chehab }
4910c0d06caSMauro Carvalho Chehab 
4920c0d06caSMauro Carvalho Chehab 
4936332a6ceSGreg Kroah-Hartman static struct class pvr2_class = {
4946332a6ceSGreg Kroah-Hartman 	.name		= "pvrusb2",
4956332a6ceSGreg Kroah-Hartman 	.dev_release	= pvr2_sysfs_release,
4966332a6ceSGreg Kroah-Hartman };
4976332a6ceSGreg Kroah-Hartman 
4986332a6ceSGreg Kroah-Hartman 
class_dev_destroy(struct pvr2_sysfs * sfp)4990c0d06caSMauro Carvalho Chehab static void class_dev_destroy(struct pvr2_sysfs *sfp)
5000c0d06caSMauro Carvalho Chehab {
5010c0d06caSMauro Carvalho Chehab 	struct device *dev;
5020c0d06caSMauro Carvalho Chehab 	if (!sfp->class_dev) return;
5030c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
5040c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_tear_down_debugifc(sfp);
5050c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
5060c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_tear_down_controls(sfp);
5070c0d06caSMauro Carvalho Chehab 	if (sfp->hdw_desc_created_ok) {
5080c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
5090c0d06caSMauro Carvalho Chehab 				   &sfp->attr_hdw_desc);
5100c0d06caSMauro Carvalho Chehab 	}
5110c0d06caSMauro Carvalho Chehab 	if (sfp->hdw_name_created_ok) {
5120c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
5130c0d06caSMauro Carvalho Chehab 				   &sfp->attr_hdw_name);
5140c0d06caSMauro Carvalho Chehab 	}
5150c0d06caSMauro Carvalho Chehab 	if (sfp->bus_info_created_ok) {
5160c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
5170c0d06caSMauro Carvalho Chehab 					 &sfp->attr_bus_info);
5180c0d06caSMauro Carvalho Chehab 	}
5190c0d06caSMauro Carvalho Chehab 	if (sfp->v4l_minor_number_created_ok) {
5200c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
5210c0d06caSMauro Carvalho Chehab 					 &sfp->attr_v4l_minor_number);
5220c0d06caSMauro Carvalho Chehab 	}
5230c0d06caSMauro Carvalho Chehab 	if (sfp->v4l_radio_minor_number_created_ok) {
5240c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
5250c0d06caSMauro Carvalho Chehab 					 &sfp->attr_v4l_radio_minor_number);
5260c0d06caSMauro Carvalho Chehab 	}
5270c0d06caSMauro Carvalho Chehab 	if (sfp->unit_number_created_ok) {
5280c0d06caSMauro Carvalho Chehab 		device_remove_file(sfp->class_dev,
5290c0d06caSMauro Carvalho Chehab 					 &sfp->attr_unit_number);
5300c0d06caSMauro Carvalho Chehab 	}
5310c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
5320c0d06caSMauro Carvalho Chehab 	dev_set_drvdata(sfp->class_dev, NULL);
5330c0d06caSMauro Carvalho Chehab 	dev = sfp->class_dev->parent;
5340c0d06caSMauro Carvalho Chehab 	sfp->class_dev->parent = NULL;
5350c0d06caSMauro Carvalho Chehab 	put_device(dev);
5360c0d06caSMauro Carvalho Chehab 	device_unregister(sfp->class_dev);
5370c0d06caSMauro Carvalho Chehab 	sfp->class_dev = NULL;
5380c0d06caSMauro Carvalho Chehab }
5390c0d06caSMauro Carvalho Chehab 
5400c0d06caSMauro Carvalho Chehab 
v4l_minor_number_show(struct device * class_dev,struct device_attribute * attr,char * buf)5410c0d06caSMauro Carvalho Chehab static ssize_t v4l_minor_number_show(struct device *class_dev,
5420c0d06caSMauro Carvalho Chehab 				     struct device_attribute *attr, char *buf)
5430c0d06caSMauro Carvalho Chehab {
5440c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
5450c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
5460c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
547*13e6756bSye xingchen 	return sysfs_emit(buf, "%d\n",
5480c0d06caSMauro Carvalho Chehab 			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
5490c0d06caSMauro Carvalho Chehab 						       pvr2_v4l_type_video));
5500c0d06caSMauro Carvalho Chehab }
5510c0d06caSMauro Carvalho Chehab 
5520c0d06caSMauro Carvalho Chehab 
bus_info_show(struct device * class_dev,struct device_attribute * attr,char * buf)5530c0d06caSMauro Carvalho Chehab static ssize_t bus_info_show(struct device *class_dev,
5540c0d06caSMauro Carvalho Chehab 			     struct device_attribute *attr, char *buf)
5550c0d06caSMauro Carvalho Chehab {
5560c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
5570c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
5580c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
559*13e6756bSye xingchen 	return sysfs_emit(buf, "%s\n",
5600c0d06caSMauro Carvalho Chehab 			 pvr2_hdw_get_bus_info(sfp->channel.hdw));
5610c0d06caSMauro Carvalho Chehab }
5620c0d06caSMauro Carvalho Chehab 
5630c0d06caSMauro Carvalho Chehab 
hdw_name_show(struct device * class_dev,struct device_attribute * attr,char * buf)5640c0d06caSMauro Carvalho Chehab static ssize_t hdw_name_show(struct device *class_dev,
5650c0d06caSMauro Carvalho Chehab 			     struct device_attribute *attr, char *buf)
5660c0d06caSMauro Carvalho Chehab {
5670c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
5680c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
5690c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
570*13e6756bSye xingchen 	return sysfs_emit(buf, "%s\n",
5710c0d06caSMauro Carvalho Chehab 			 pvr2_hdw_get_type(sfp->channel.hdw));
5720c0d06caSMauro Carvalho Chehab }
5730c0d06caSMauro Carvalho Chehab 
5740c0d06caSMauro Carvalho Chehab 
hdw_desc_show(struct device * class_dev,struct device_attribute * attr,char * buf)5750c0d06caSMauro Carvalho Chehab static ssize_t hdw_desc_show(struct device *class_dev,
5760c0d06caSMauro Carvalho Chehab 			     struct device_attribute *attr, char *buf)
5770c0d06caSMauro Carvalho Chehab {
5780c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
5790c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
5800c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
581*13e6756bSye xingchen 	return sysfs_emit(buf, "%s\n",
5820c0d06caSMauro Carvalho Chehab 			 pvr2_hdw_get_desc(sfp->channel.hdw));
5830c0d06caSMauro Carvalho Chehab }
5840c0d06caSMauro Carvalho Chehab 
5850c0d06caSMauro Carvalho Chehab 
v4l_radio_minor_number_show(struct device * class_dev,struct device_attribute * attr,char * buf)5860c0d06caSMauro Carvalho Chehab static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
5870c0d06caSMauro Carvalho Chehab 					   struct device_attribute *attr,
5880c0d06caSMauro Carvalho Chehab 					   char *buf)
5890c0d06caSMauro Carvalho Chehab {
5900c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
5910c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
5920c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
593*13e6756bSye xingchen 	return sysfs_emit(buf, "%d\n",
5940c0d06caSMauro Carvalho Chehab 			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
5950c0d06caSMauro Carvalho Chehab 						       pvr2_v4l_type_radio));
5960c0d06caSMauro Carvalho Chehab }
5970c0d06caSMauro Carvalho Chehab 
5980c0d06caSMauro Carvalho Chehab 
unit_number_show(struct device * class_dev,struct device_attribute * attr,char * buf)5990c0d06caSMauro Carvalho Chehab static ssize_t unit_number_show(struct device *class_dev,
6000c0d06caSMauro Carvalho Chehab 				struct device_attribute *attr, char *buf)
6010c0d06caSMauro Carvalho Chehab {
6020c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
6030c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
6040c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
605*13e6756bSye xingchen 	return sysfs_emit(buf, "%d\n",
6060c0d06caSMauro Carvalho Chehab 			 pvr2_hdw_get_unit_number(sfp->channel.hdw));
6070c0d06caSMauro Carvalho Chehab }
6080c0d06caSMauro Carvalho Chehab 
6090c0d06caSMauro Carvalho Chehab 
class_dev_create(struct pvr2_sysfs * sfp)6106332a6ceSGreg Kroah-Hartman static void class_dev_create(struct pvr2_sysfs *sfp)
6110c0d06caSMauro Carvalho Chehab {
6120c0d06caSMauro Carvalho Chehab 	struct usb_device *usb_dev;
6130c0d06caSMauro Carvalho Chehab 	struct device *class_dev;
6140c0d06caSMauro Carvalho Chehab 	int ret;
6150c0d06caSMauro Carvalho Chehab 
6160c0d06caSMauro Carvalho Chehab 	usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
6170c0d06caSMauro Carvalho Chehab 	if (!usb_dev) return;
6180c0d06caSMauro Carvalho Chehab 	class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
6190c0d06caSMauro Carvalho Chehab 	if (!class_dev) return;
6200c0d06caSMauro Carvalho Chehab 
6210c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
6220c0d06caSMauro Carvalho Chehab 
6236332a6ceSGreg Kroah-Hartman 	class_dev->class = &pvr2_class;
6240c0d06caSMauro Carvalho Chehab 
6250c0d06caSMauro Carvalho Chehab 	dev_set_name(class_dev, "%s",
6260c0d06caSMauro Carvalho Chehab 		     pvr2_hdw_get_device_identifier(sfp->channel.hdw));
6270c0d06caSMauro Carvalho Chehab 
6280c0d06caSMauro Carvalho Chehab 	class_dev->parent = get_device(&usb_dev->dev);
6290c0d06caSMauro Carvalho Chehab 
6300c0d06caSMauro Carvalho Chehab 	sfp->class_dev = class_dev;
6310c0d06caSMauro Carvalho Chehab 	dev_set_drvdata(class_dev, sfp);
6320c0d06caSMauro Carvalho Chehab 	ret = device_register(class_dev);
6330c0d06caSMauro Carvalho Chehab 	if (ret) {
6340c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
6350c0d06caSMauro Carvalho Chehab 			   "device_register failed");
6360c0d06caSMauro Carvalho Chehab 		put_device(class_dev);
6370c0d06caSMauro Carvalho Chehab 		return;
6380c0d06caSMauro Carvalho Chehab 	}
6390c0d06caSMauro Carvalho Chehab 
6400c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&sfp->attr_v4l_minor_number.attr);
6410c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
6420c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
6430c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
6440c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_minor_number.store = NULL;
6450c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,
6460c0d06caSMauro Carvalho Chehab 				       &sfp->attr_v4l_minor_number);
6470c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
6480c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
6490c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
6500c0d06caSMauro Carvalho Chehab 			   ret);
6510c0d06caSMauro Carvalho Chehab 	} else {
6520c0d06caSMauro Carvalho Chehab 		sfp->v4l_minor_number_created_ok = !0;
6530c0d06caSMauro Carvalho Chehab 	}
6540c0d06caSMauro Carvalho Chehab 
6550c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr);
6560c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
6570c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
6580c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
6590c0d06caSMauro Carvalho Chehab 	sfp->attr_v4l_radio_minor_number.store = NULL;
6600c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,
6610c0d06caSMauro Carvalho Chehab 				       &sfp->attr_v4l_radio_minor_number);
6620c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
6630c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
6640c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
6650c0d06caSMauro Carvalho Chehab 			   ret);
6660c0d06caSMauro Carvalho Chehab 	} else {
6670c0d06caSMauro Carvalho Chehab 		sfp->v4l_radio_minor_number_created_ok = !0;
6680c0d06caSMauro Carvalho Chehab 	}
6690c0d06caSMauro Carvalho Chehab 
6700c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&sfp->attr_unit_number.attr);
6710c0d06caSMauro Carvalho Chehab 	sfp->attr_unit_number.attr.name = "unit_number";
6720c0d06caSMauro Carvalho Chehab 	sfp->attr_unit_number.attr.mode = S_IRUGO;
6730c0d06caSMauro Carvalho Chehab 	sfp->attr_unit_number.show = unit_number_show;
6740c0d06caSMauro Carvalho Chehab 	sfp->attr_unit_number.store = NULL;
6750c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
6760c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
6770c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
6780c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
6790c0d06caSMauro Carvalho Chehab 			   ret);
6800c0d06caSMauro Carvalho Chehab 	} else {
6810c0d06caSMauro Carvalho Chehab 		sfp->unit_number_created_ok = !0;
6820c0d06caSMauro Carvalho Chehab 	}
6830c0d06caSMauro Carvalho Chehab 
6840c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&sfp->attr_bus_info.attr);
6850c0d06caSMauro Carvalho Chehab 	sfp->attr_bus_info.attr.name = "bus_info_str";
6860c0d06caSMauro Carvalho Chehab 	sfp->attr_bus_info.attr.mode = S_IRUGO;
6870c0d06caSMauro Carvalho Chehab 	sfp->attr_bus_info.show = bus_info_show;
6880c0d06caSMauro Carvalho Chehab 	sfp->attr_bus_info.store = NULL;
6890c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,
6900c0d06caSMauro Carvalho Chehab 				       &sfp->attr_bus_info);
6910c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
6920c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
6930c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
6940c0d06caSMauro Carvalho Chehab 			   ret);
6950c0d06caSMauro Carvalho Chehab 	} else {
6960c0d06caSMauro Carvalho Chehab 		sfp->bus_info_created_ok = !0;
6970c0d06caSMauro Carvalho Chehab 	}
6980c0d06caSMauro Carvalho Chehab 
6990c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&sfp->attr_hdw_name.attr);
7000c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_name.attr.name = "device_hardware_type";
7010c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_name.attr.mode = S_IRUGO;
7020c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_name.show = hdw_name_show;
7030c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_name.store = NULL;
7040c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,
7050c0d06caSMauro Carvalho Chehab 				 &sfp->attr_hdw_name);
7060c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
7070c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
7080c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
7090c0d06caSMauro Carvalho Chehab 			   ret);
7100c0d06caSMauro Carvalho Chehab 	} else {
7110c0d06caSMauro Carvalho Chehab 		sfp->hdw_name_created_ok = !0;
7120c0d06caSMauro Carvalho Chehab 	}
7130c0d06caSMauro Carvalho Chehab 
7140c0d06caSMauro Carvalho Chehab 	sysfs_attr_init(&sfp->attr_hdw_desc.attr);
7150c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_desc.attr.name = "device_hardware_description";
7160c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_desc.attr.mode = S_IRUGO;
7170c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_desc.show = hdw_desc_show;
7180c0d06caSMauro Carvalho Chehab 	sfp->attr_hdw_desc.store = NULL;
7190c0d06caSMauro Carvalho Chehab 	ret = device_create_file(sfp->class_dev,
7200c0d06caSMauro Carvalho Chehab 				 &sfp->attr_hdw_desc);
7210c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
7220c0d06caSMauro Carvalho Chehab 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
7230c0d06caSMauro Carvalho Chehab 			   "device_create_file error: %d",
7240c0d06caSMauro Carvalho Chehab 			   ret);
7250c0d06caSMauro Carvalho Chehab 	} else {
7260c0d06caSMauro Carvalho Chehab 		sfp->hdw_desc_created_ok = !0;
7270c0d06caSMauro Carvalho Chehab 	}
7280c0d06caSMauro Carvalho Chehab 
7290c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_add_controls(sfp);
7300c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
7310c0d06caSMauro Carvalho Chehab 	pvr2_sysfs_add_debugifc(sfp);
7320c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
7330c0d06caSMauro Carvalho Chehab }
7340c0d06caSMauro Carvalho Chehab 
7350c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_internal_check(struct pvr2_channel * chp)7360c0d06caSMauro Carvalho Chehab static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
7370c0d06caSMauro Carvalho Chehab {
7380c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
7390c0d06caSMauro Carvalho Chehab 	sfp = container_of(chp,struct pvr2_sysfs,channel);
7400c0d06caSMauro Carvalho Chehab 	if (!sfp->channel.mc_head->disconnect_flag) return;
7410c0d06caSMauro Carvalho Chehab 	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
7420c0d06caSMauro Carvalho Chehab 	class_dev_destroy(sfp);
7430c0d06caSMauro Carvalho Chehab 	pvr2_channel_done(&sfp->channel);
7440c0d06caSMauro Carvalho Chehab 	kfree(sfp);
7450c0d06caSMauro Carvalho Chehab }
7460c0d06caSMauro Carvalho Chehab 
7470c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_create(struct pvr2_context * mp)7486332a6ceSGreg Kroah-Hartman void pvr2_sysfs_create(struct pvr2_context *mp)
7490c0d06caSMauro Carvalho Chehab {
7500c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
7510c0d06caSMauro Carvalho Chehab 	sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
7526332a6ceSGreg Kroah-Hartman 	if (!sfp)
7536332a6ceSGreg Kroah-Hartman 		return;
7540c0d06caSMauro Carvalho Chehab 	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
7550c0d06caSMauro Carvalho Chehab 	pvr2_channel_init(&sfp->channel,mp);
7560c0d06caSMauro Carvalho Chehab 	sfp->channel.check_func = pvr2_sysfs_internal_check;
7570c0d06caSMauro Carvalho Chehab 
7586332a6ceSGreg Kroah-Hartman 	class_dev_create(sfp);
7590c0d06caSMauro Carvalho Chehab }
7600c0d06caSMauro Carvalho Chehab 
7610c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_class_create(void)7626332a6ceSGreg Kroah-Hartman void pvr2_sysfs_class_create(void)
7630c0d06caSMauro Carvalho Chehab {
7646332a6ceSGreg Kroah-Hartman 	if (class_register(&pvr2_class))
7656332a6ceSGreg Kroah-Hartman 		pvr2_sysfs_trace("Registration failed for pvr2_sysfs_class");
7660c0d06caSMauro Carvalho Chehab }
7670c0d06caSMauro Carvalho Chehab 
7680c0d06caSMauro Carvalho Chehab 
pvr2_sysfs_class_destroy(void)7696332a6ceSGreg Kroah-Hartman void pvr2_sysfs_class_destroy(void)
7700c0d06caSMauro Carvalho Chehab {
7716332a6ceSGreg Kroah-Hartman 	class_unregister(&pvr2_class);
7720c0d06caSMauro Carvalho Chehab }
7730c0d06caSMauro Carvalho Chehab 
7740c0d06caSMauro Carvalho Chehab 
7750c0d06caSMauro Carvalho Chehab #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
debuginfo_show(struct device * class_dev,struct device_attribute * attr,char * buf)7760c0d06caSMauro Carvalho Chehab static ssize_t debuginfo_show(struct device *class_dev,
7770c0d06caSMauro Carvalho Chehab 			      struct device_attribute *attr, char *buf)
7780c0d06caSMauro Carvalho Chehab {
7790c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
7800c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
7810c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
7820c0d06caSMauro Carvalho Chehab 	pvr2_hdw_trigger_module_log(sfp->channel.hdw);
7830c0d06caSMauro Carvalho Chehab 	return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
7840c0d06caSMauro Carvalho Chehab }
7850c0d06caSMauro Carvalho Chehab 
7860c0d06caSMauro Carvalho Chehab 
debugcmd_show(struct device * class_dev,struct device_attribute * attr,char * buf)7870c0d06caSMauro Carvalho Chehab static ssize_t debugcmd_show(struct device *class_dev,
7880c0d06caSMauro Carvalho Chehab 			     struct device_attribute *attr, char *buf)
7890c0d06caSMauro Carvalho Chehab {
7900c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
7910c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
7920c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
7930c0d06caSMauro Carvalho Chehab 	return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
7940c0d06caSMauro Carvalho Chehab }
7950c0d06caSMauro Carvalho Chehab 
7960c0d06caSMauro Carvalho Chehab 
debugcmd_store(struct device * class_dev,struct device_attribute * attr,const char * buf,size_t count)7970c0d06caSMauro Carvalho Chehab static ssize_t debugcmd_store(struct device *class_dev,
7980c0d06caSMauro Carvalho Chehab 			      struct device_attribute *attr,
7990c0d06caSMauro Carvalho Chehab 			      const char *buf, size_t count)
8000c0d06caSMauro Carvalho Chehab {
8010c0d06caSMauro Carvalho Chehab 	struct pvr2_sysfs *sfp;
8020c0d06caSMauro Carvalho Chehab 	int ret;
8030c0d06caSMauro Carvalho Chehab 
8040c0d06caSMauro Carvalho Chehab 	sfp = dev_get_drvdata(class_dev);
8050c0d06caSMauro Carvalho Chehab 	if (!sfp) return -EINVAL;
8060c0d06caSMauro Carvalho Chehab 
8070c0d06caSMauro Carvalho Chehab 	ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
8080c0d06caSMauro Carvalho Chehab 	if (ret < 0) return ret;
8090c0d06caSMauro Carvalho Chehab 	return count;
8100c0d06caSMauro Carvalho Chehab }
8110c0d06caSMauro Carvalho Chehab #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
812