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

📄 pvrusb2-sysfs.c

📁 linux内核源码
💻 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 "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 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 device_attribute attr_v4l_minor_number;	struct device_attribute attr_v4l_radio_minor_number;	struct device_attribute attr_unit_number;	struct device_attribute attr_bus_info;	int v4l_minor_number_created_ok;	int v4l_radio_minor_number_created_ok;	int unit_number_created_ok;	int bus_info_created_ok;};#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFCstruct pvr2_sysfs_debugifc {	struct device_attribute attr_debugcmd;	struct device_attribute attr_debuginfo;	int debugcmd_created_ok;	int debuginfo_created_ok;};#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */struct pvr2_sysfs_ctl_item {	struct device_attribute attr_name;	struct device_attribute attr_type;	struct device_attribute attr_min;	struct device_attribute attr_max;	struct device_attribute attr_enum;	struct device_attribute attr_bits;	struct device_attribute attr_val;	struct device_attribute attr_custom;	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *chptr;	struct pvr2_sysfs_ctl_item *item_next;	struct attribute *attr_gen[7];	struct attribute_group grp;	int created_ok;	char name[80];};struct pvr2_sysfs_class {	struct class class;};static ssize_t show_name(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	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);	if (!name) return -EINVAL;	return scnprintf(buf,PAGE_SIZE,"%s\n",name);}static ssize_t show_type(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	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);	switch (tp) {	case pvr2_ctl_int: name = "integer"; break;	case pvr2_ctl_enum: name = "enum"; break;	case pvr2_ctl_bitmask: name = "bitmask"; break;	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);	if (!name) return -EINVAL;	return scnprintf(buf,PAGE_SIZE,"%s\n",name);}static ssize_t show_min(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	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);}static ssize_t show_max(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	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);}static ssize_t show_val_norm(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int val,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);	if (ret < 0) return ret;	ret = pvr2_ctrl_value_to_sym(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);	buf[cnt] = '\n';	return cnt+1;}static ssize_t show_val_custom(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	int val,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);	if (ret < 0) return ret;	ret = pvr2_ctrl_custom_value_to_sym(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);	buf[cnt] = '\n';	return cnt+1;}static ssize_t show_enum(int id,struct device *class_dev,char *buf){	struct pvr2_ctrl *cptr;	struct pvr2_sysfs *sfp;	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);	bcnt = 0;	for (val = 0; val < ecnt; val++) {		pvr2_ctrl_get_valname(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);	return bcnt;}static ssize_t show_bits(int id,struct device *class_dev,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);	bcnt = 0;	for (msk = 1; valid_bits; msk <<= 1) {		if (!(msk & valid_bits)) continue;		valid_bits &= ~msk;		pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);		bcnt += ccnt;		if (bcnt >= PAGE_SIZE) break;		buf[bcnt] = '\n';		bcnt++;	}	pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id);	return bcnt;}static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,			 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);	} else {		ret = pvr2_ctrl_sym_to_value(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);	return ret;}static ssize_t store_val_norm(int id,struct device *class_dev,			     const char *buf,size_t count){	struct pvr2_sysfs *sfp;	int ret;	sfp = (struct pvr2_sysfs *)class_dev->driver_data;	ret = store_val_any(id,0,sfp,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){	struct pvr2_sysfs *sfp;	int ret;	sfp = (struct pvr2_sysfs *)class_dev->driver_data;	ret = store_val_any(id,1,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 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),

⌨️ 快捷键说明

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