⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pvrusb2-sysfs.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  $Id$ * *  Copyright (C) 2005 Mike Isely <isely@pobox.com> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <linux/string.h>#include <linux/slab.h>#include <asm/semaphore.h>#include "compat.h"#include "pvrusb2-sysfs.h"#include "pvrusb2-hdw.h"#include "pvrusb2-debug.h"#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC#include "pvrusb2-debugifc.h"#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)struct pvr2_sysfs {	struct pvr2_channel channel;	struct class_device *class_dev;#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC	struct pvr2_sysfs_debugifc *debugifc;#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */	struct pvr2_sysfs_ctl_item *item_first;	struct pvr2_sysfs_ctl_item *item_last;	struct sysfs_ops kops;	struct kobj_type ktype;	struct class_device_attribute attr_v4l_minor_number;	struct class_device_attribute attr_unit_number;};#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFCstruct pvr2_sysfs_debugifc {	struct class_device_attribute attr_debugcmd;	struct class_device_attribute attr_debuginfo;};#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */struct pvr2_sysfs_ctl_item {	struct class_device_attribute attr_name;	struct class_device_attribute attr_min;	struct class_device_attribute attr_max;	struct class_device_attribute attr_enum;	struct class_device_attribute attr_val;	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *chptr;	struct pvr2_sysfs_ctl_item *item_next;	struct attribute *attr_gen[5];	struct attribute_group grp;	char name[80];};struct pvr2_sysfs_class {	struct class class;};static ssize_t show_name(int id,struct class_device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	const char *name;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	if (!sfp) return -EINVAL;	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	name = pvr2_ctrl_get_desc(cptr);	pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name);	if (!name) return -EINVAL;	return scnprintf(buf,PAGE_SIZE,"%s\n",name);}static ssize_t show_min(int id,struct class_device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int val;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	if (!sfp) return -EINVAL;	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	val = pvr2_ctrl_get_min_value(cptr);	pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %d",sfp,id,val);	return scnprintf(buf,PAGE_SIZE,"%d\n",val);}static ssize_t show_max(int id,struct class_device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int val;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	if (!sfp) return -EINVAL;	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	val = pvr2_ctrl_get_max_value(cptr);	pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %d",sfp,id,val);	return scnprintf(buf,PAGE_SIZE,"%d\n",val);}static ssize_t show_val_int(int id,struct class_device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int val;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	if (!sfp) return -EINVAL;	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	val = pvr2_ctrl_get_value(cptr);	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_int(cid=%d) is %d",			 sfp,id,val);	return scnprintf(buf,PAGE_SIZE,"%d\n",val);}static ssize_t show_val_enum(int id,struct class_device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int val;	const char *name;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	if (!sfp) return -EINVAL;	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	val = pvr2_ctrl_get_value(cptr);	name = pvr2_ctrl_get_value_name(cptr,val);	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_enum(cid=%d) is %s (%d)",			 sfp,id,name,val);	return scnprintf(buf,PAGE_SIZE,"%s\n",name);}static ssize_t show_enum(int id,struct class_device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int minval,maxval,val;	const char *name;	ssize_t cnt = 0;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	if (!sfp) return -EINVAL;	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	minval = pvr2_ctrl_get_min_value(cptr);	maxval = pvr2_ctrl_get_max_value(cptr);	for (val = minval; val <= maxval; val++) {		name = pvr2_ctrl_get_value_name(cptr,val);		cnt += scnprintf(buf+cnt,PAGE_SIZE-cnt,"%s\n",name);	}	pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id);	return cnt;}static int store_val_any(int id,struct pvr2_sysfs *sfp,			 const char *buf,unsigned int count){	struct pvr2_ctrl *cptr;	int val,minval,maxval;	int ch,ret;	const char *nv;	unsigned int nl;	int negfl;	/* Trim leading / trailing whitespace */	while (count) {		ch = buf[0];		if ((ch > 32) && (ch < 127)) break;		buf++;		count--;	}	while (count) {		ch = buf[count-1];		if ((ch > 32) && (ch < 127)) break;		count--;	}	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);	if (!pvr2_ctrl_is_valid(cptr)) return -EINVAL;	/* Is this an enum?  Look for a string value */	minval = pvr2_ctrl_get_min_value(cptr);	maxval = pvr2_ctrl_get_max_value(cptr);	for (val = minval; val <= maxval; val++) {		nv = pvr2_ctrl_get_value_name(cptr,val);		if ((!nv) && (val == minval)) break; /* Not an enum */		pvr2_sysfs_trace("pvr2_sysfs(%p) trying ctl_id %d val %d",				 sfp,id,val);		if (!nv) {			pvr2_sysfs_trace("pvr2_sysfs(%p) no pointer",sfp);			continue;		}		nl = strlen(nv);		if (nl != count) {			pvr2_sysfs_trace("pvr2_sysfs(%p) count mismatch"					 " %d != %d",					 sfp,count,nl);			continue;		}		if (memcmp(buf,nv,nl)) {			pvr2_sysfs_trace(				"pvr2_sysfs(%p) name mismatch"				" >>%.*s<< != >>%.*s<<",				sfp,nl,buf,nl,nv);			continue;		}		pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)"				 " is enum %s",				 sfp,id,nv);		ret = pvr2_ctrl_set_value(cptr,val);		pvr2_hdw_commit_ctl(sfp->channel.hdw);		return 0;	}	if (val > minval) {		pvr2_sysfs_trace(			"pvr2_sysfs(%p) store_val_any(cid=%d)"			" unmatched enum >>%.*s<<",			sfp,id,count,buf);	}	/* Try to parse as a number */	negfl = 0;	val = 0;	if (count) {		if (buf[0] == '-') {			negfl = !0;			buf++;			count--;		} else if (buf[0] == '+') {			buf++;			count--;		}	}	while (count) {		ch = buf[0];		if ((ch < '0') || (ch > '9')) break;		val = val * 10;		val += (ch - '0');		buf++;		count--;	}	if (!count) {		if (negfl) val = -val;		pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_any(cid=%d)"				 " int is %d",				 sfp,id,val);		ret = pvr2_ctrl_set_value(cptr,val);		pvr2_hdw_commit_ctl(sfp->channel.hdw);		return ret;	}	return -EINVAL;}static int store_val_multi(int id,struct pvr2_sysfs *sfp,			   const char *buf,unsigned int count){	unsigned int count2;	int ret;	while (count) {		count2 = 0;		while ((count2 < count) && (buf[count2] != '\n')) count2++;		ret = store_val_any(id,sfp,buf,count2);		if (ret < 0) return ret;		if (count2 < count) count2++;		buf += count2;		count -= count2;	}	return 0;}static ssize_t store_val_int(int id,struct class_device *class_dev,			     const char *buf,size_t count){	struct pvr2_sysfs *sfp;	int ret;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	ret = store_val_multi(id,sfp,buf,count);	if (!ret) ret = count;	return ret;}static ssize_t store_val_enum(int id,struct class_device *class_dev,			      const char *buf,size_t count){	struct pvr2_sysfs *sfp;	int ret;	sfp = (struct pvr2_sysfs *)class_dev->class_data;	ret = store_val_multi(id,sfp,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 class_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 class_device *class_dev,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 class_device *class_dev,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_min,ctl_id) \CREATE_SHOW_INSTANCE(show_max,ctl_id) \CREATE_SHOW_INSTANCE(show_val_int,ctl_id) \CREATE_SHOW_INSTANCE(show_val_enum,ctl_id) \CREATE_SHOW_INSTANCE(show_enum,ctl_id) \CREATE_STORE_INSTANCE(store_val_int,ctl_id) \CREATE_STORE_INSTANCE(store_val_enum,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)struct pvr2_sysfs_func_set {	ssize_t (*show_name)(struct class_device *,char *);	ssize_t (*show_min)(struct class_device *,char *);	ssize_t (*show_max)(struct class_device *,char *);	ssize_t (*show_enum)(struct class_device *,char *);	ssize_t (*show_val_int)(struct class_device *,char *);	ssize_t (*show_val_enum)(struct class_device *,char *);	ssize_t (*store_val_int)(struct class_device *,				 const char *,size_t);	ssize_t (*store_val_enum)(struct class_device *,				  const char *,size_t);};#define INIT_BATCH(ctl_id) \[ctl_id] = { \

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -