cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pvrusb2-sysfs.c (23349B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *
      4 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
      5 */
      6
      7#include <linux/string.h>
      8#include <linux/slab.h>
      9#include "pvrusb2-sysfs.h"
     10#include "pvrusb2-hdw.h"
     11#include "pvrusb2-debug.h"
     12#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
     13#include "pvrusb2-debugifc.h"
     14#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
     15
     16#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
     17
     18struct pvr2_sysfs {
     19	struct pvr2_channel channel;
     20	struct device *class_dev;
     21#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
     22	struct pvr2_sysfs_debugifc *debugifc;
     23#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
     24	struct pvr2_sysfs_ctl_item *item_first;
     25	struct pvr2_sysfs_ctl_item *item_last;
     26	struct device_attribute attr_v4l_minor_number;
     27	struct device_attribute attr_v4l_radio_minor_number;
     28	struct device_attribute attr_unit_number;
     29	struct device_attribute attr_bus_info;
     30	struct device_attribute attr_hdw_name;
     31	struct device_attribute attr_hdw_desc;
     32	int v4l_minor_number_created_ok;
     33	int v4l_radio_minor_number_created_ok;
     34	int unit_number_created_ok;
     35	int bus_info_created_ok;
     36	int hdw_name_created_ok;
     37	int hdw_desc_created_ok;
     38};
     39
     40#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
     41struct pvr2_sysfs_debugifc {
     42	struct device_attribute attr_debugcmd;
     43	struct device_attribute attr_debuginfo;
     44	int debugcmd_created_ok;
     45	int debuginfo_created_ok;
     46};
     47#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
     48
     49struct pvr2_sysfs_ctl_item {
     50	struct device_attribute attr_name;
     51	struct device_attribute attr_type;
     52	struct device_attribute attr_min;
     53	struct device_attribute attr_max;
     54	struct device_attribute attr_def;
     55	struct device_attribute attr_enum;
     56	struct device_attribute attr_bits;
     57	struct device_attribute attr_val;
     58	struct device_attribute attr_custom;
     59	struct pvr2_ctrl *cptr;
     60	int ctl_id;
     61	struct pvr2_sysfs *chptr;
     62	struct pvr2_sysfs_ctl_item *item_next;
     63	struct attribute *attr_gen[8];
     64	struct attribute_group grp;
     65	int created_ok;
     66	char name[80];
     67};
     68
     69struct pvr2_sysfs_class {
     70	struct class class;
     71};
     72
     73static ssize_t show_name(struct device *class_dev,
     74			 struct device_attribute *attr,
     75			 char *buf)
     76{
     77	struct pvr2_sysfs_ctl_item *cip;
     78	const char *name;
     79	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
     80	name = pvr2_ctrl_get_desc(cip->cptr);
     81	pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
     82			 cip->chptr, cip->ctl_id, name);
     83	if (!name) return -EINVAL;
     84	return scnprintf(buf, PAGE_SIZE, "%s\n", name);
     85}
     86
     87static ssize_t show_type(struct device *class_dev,
     88			 struct device_attribute *attr,
     89			 char *buf)
     90{
     91	struct pvr2_sysfs_ctl_item *cip;
     92	const char *name;
     93	enum pvr2_ctl_type tp;
     94	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
     95	tp = pvr2_ctrl_get_type(cip->cptr);
     96	switch (tp) {
     97	case pvr2_ctl_int: name = "integer"; break;
     98	case pvr2_ctl_enum: name = "enum"; break;
     99	case pvr2_ctl_bitmask: name = "bitmask"; break;
    100	case pvr2_ctl_bool: name = "boolean"; break;
    101	default: name = "?"; break;
    102	}
    103	pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
    104			 cip->chptr, cip->ctl_id, name);
    105	return scnprintf(buf, PAGE_SIZE, "%s\n", name);
    106}
    107
    108static ssize_t show_min(struct device *class_dev,
    109			struct device_attribute *attr,
    110			char *buf)
    111{
    112	struct pvr2_sysfs_ctl_item *cip;
    113	long val;
    114	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
    115	val = pvr2_ctrl_get_min(cip->cptr);
    116	pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
    117			 cip->chptr, cip->ctl_id, val);
    118	return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
    119}
    120
    121static ssize_t show_max(struct device *class_dev,
    122			struct device_attribute *attr,
    123			char *buf)
    124{
    125	struct pvr2_sysfs_ctl_item *cip;
    126	long val;
    127	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
    128	val = pvr2_ctrl_get_max(cip->cptr);
    129	pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
    130			 cip->chptr, cip->ctl_id, val);
    131	return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
    132}
    133
    134static ssize_t show_def(struct device *class_dev,
    135			struct device_attribute *attr,
    136			char *buf)
    137{
    138	struct pvr2_sysfs_ctl_item *cip;
    139	int val;
    140	int ret;
    141	unsigned int cnt = 0;
    142	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
    143	ret = pvr2_ctrl_get_def(cip->cptr, &val);
    144	if (ret < 0) return ret;
    145	ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
    146				     buf, PAGE_SIZE - 1, &cnt);
    147	pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)",
    148			 cip->chptr, cip->ctl_id, cnt, buf, val);
    149	buf[cnt] = '\n';
    150	return cnt + 1;
    151}
    152
    153static ssize_t show_val_norm(struct device *class_dev,
    154			     struct device_attribute *attr,
    155			     char *buf)
    156{
    157	struct pvr2_sysfs_ctl_item *cip;
    158	int val;
    159	int ret;
    160	unsigned int cnt = 0;
    161	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
    162	ret = pvr2_ctrl_get_value(cip->cptr, &val);
    163	if (ret < 0) return ret;
    164	ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
    165				     buf, PAGE_SIZE - 1, &cnt);
    166	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
    167			 cip->chptr, cip->ctl_id, cnt, buf, val);
    168	buf[cnt] = '\n';
    169	return cnt+1;
    170}
    171
    172static ssize_t show_val_custom(struct device *class_dev,
    173			       struct device_attribute *attr,
    174			       char *buf)
    175{
    176	struct pvr2_sysfs_ctl_item *cip;
    177	int val;
    178	int ret;
    179	unsigned int cnt = 0;
    180	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
    181	ret = pvr2_ctrl_get_value(cip->cptr, &val);
    182	if (ret < 0) return ret;
    183	ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
    184					    buf, PAGE_SIZE - 1, &cnt);
    185	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
    186			 cip->chptr, cip->ctl_id, cnt, buf, val);
    187	buf[cnt] = '\n';
    188	return cnt+1;
    189}
    190
    191static ssize_t show_enum(struct device *class_dev,
    192			 struct device_attribute *attr,
    193			 char *buf)
    194{
    195	struct pvr2_sysfs_ctl_item *cip;
    196	long val;
    197	unsigned int bcnt, ccnt, ecnt;
    198	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
    199	ecnt = pvr2_ctrl_get_cnt(cip->cptr);
    200	bcnt = 0;
    201	for (val = 0; val < ecnt; val++) {
    202		pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
    203				      PAGE_SIZE - bcnt, &ccnt);
    204		if (!ccnt) continue;
    205		bcnt += ccnt;
    206		if (bcnt >= PAGE_SIZE) break;
    207		buf[bcnt] = '\n';
    208		bcnt++;
    209	}
    210	pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
    211			 cip->chptr, cip->ctl_id);
    212	return bcnt;
    213}
    214
    215static ssize_t show_bits(struct device *class_dev,
    216			 struct device_attribute *attr,
    217			 char *buf)
    218{
    219	struct pvr2_sysfs_ctl_item *cip;
    220	int valid_bits, msk;
    221	unsigned int bcnt, ccnt;
    222	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
    223	valid_bits = pvr2_ctrl_get_mask(cip->cptr);
    224	bcnt = 0;
    225	for (msk = 1; valid_bits; msk <<= 1) {
    226		if (!(msk & valid_bits)) continue;
    227		valid_bits &= ~msk;
    228		pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
    229				      PAGE_SIZE - bcnt, &ccnt);
    230		bcnt += ccnt;
    231		if (bcnt >= PAGE_SIZE) break;
    232		buf[bcnt] = '\n';
    233		bcnt++;
    234	}
    235	pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
    236			 cip->chptr, cip->ctl_id);
    237	return bcnt;
    238}
    239
    240static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
    241			 const char *buf,unsigned int count)
    242{
    243	int ret;
    244	int mask,val;
    245	if (customfl) {
    246		ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
    247						    &mask, &val);
    248	} else {
    249		ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
    250					     &mask, &val);
    251	}
    252	if (ret < 0) return ret;
    253	ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
    254	pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
    255	return ret;
    256}
    257
    258static ssize_t store_val_norm(struct device *class_dev,
    259			      struct device_attribute *attr,
    260			      const char *buf, size_t count)
    261{
    262	struct pvr2_sysfs_ctl_item *cip;
    263	int ret;
    264	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
    265	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
    266			 cip->chptr, cip->ctl_id, (int)count, buf);
    267	ret = store_val_any(cip, 0, buf, count);
    268	if (!ret) ret = count;
    269	return ret;
    270}
    271
    272static ssize_t store_val_custom(struct device *class_dev,
    273				struct device_attribute *attr,
    274				const char *buf, size_t count)
    275{
    276	struct pvr2_sysfs_ctl_item *cip;
    277	int ret;
    278	cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
    279	pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
    280			 cip->chptr, cip->ctl_id, (int)count, buf);
    281	ret = store_val_any(cip, 1, buf, count);
    282	if (!ret) ret = count;
    283	return ret;
    284}
    285
    286static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
    287{
    288	struct pvr2_sysfs_ctl_item *cip;
    289	struct pvr2_ctrl *cptr;
    290	unsigned int cnt,acnt;
    291	int ret;
    292
    293	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
    294	if (!cptr) return;
    295
    296	cip = kzalloc(sizeof(*cip),GFP_KERNEL);
    297	if (!cip) return;
    298	pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
    299
    300	cip->cptr = cptr;
    301	cip->ctl_id = ctl_id;
    302
    303	cip->chptr = sfp;
    304	cip->item_next = NULL;
    305	if (sfp->item_last) {
    306		sfp->item_last->item_next = cip;
    307	} else {
    308		sfp->item_first = cip;
    309	}
    310	sfp->item_last = cip;
    311
    312	sysfs_attr_init(&cip->attr_name.attr);
    313	cip->attr_name.attr.name = "name";
    314	cip->attr_name.attr.mode = S_IRUGO;
    315	cip->attr_name.show = show_name;
    316
    317	sysfs_attr_init(&cip->attr_type.attr);
    318	cip->attr_type.attr.name = "type";
    319	cip->attr_type.attr.mode = S_IRUGO;
    320	cip->attr_type.show = show_type;
    321
    322	sysfs_attr_init(&cip->attr_min.attr);
    323	cip->attr_min.attr.name = "min_val";
    324	cip->attr_min.attr.mode = S_IRUGO;
    325	cip->attr_min.show = show_min;
    326
    327	sysfs_attr_init(&cip->attr_max.attr);
    328	cip->attr_max.attr.name = "max_val";
    329	cip->attr_max.attr.mode = S_IRUGO;
    330	cip->attr_max.show = show_max;
    331
    332	sysfs_attr_init(&cip->attr_def.attr);
    333	cip->attr_def.attr.name = "def_val";
    334	cip->attr_def.attr.mode = S_IRUGO;
    335	cip->attr_def.show = show_def;
    336
    337	sysfs_attr_init(&cip->attr_val.attr);
    338	cip->attr_val.attr.name = "cur_val";
    339	cip->attr_val.attr.mode = S_IRUGO;
    340
    341	sysfs_attr_init(&cip->attr_custom.attr);
    342	cip->attr_custom.attr.name = "custom_val";
    343	cip->attr_custom.attr.mode = S_IRUGO;
    344
    345	sysfs_attr_init(&cip->attr_enum.attr);
    346	cip->attr_enum.attr.name = "enum_val";
    347	cip->attr_enum.attr.mode = S_IRUGO;
    348	cip->attr_enum.show = show_enum;
    349
    350	sysfs_attr_init(&cip->attr_bits.attr);
    351	cip->attr_bits.attr.name = "bit_val";
    352	cip->attr_bits.attr.mode = S_IRUGO;
    353	cip->attr_bits.show = show_bits;
    354
    355	if (pvr2_ctrl_is_writable(cptr)) {
    356		cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
    357		cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
    358	}
    359
    360	acnt = 0;
    361	cip->attr_gen[acnt++] = &cip->attr_name.attr;
    362	cip->attr_gen[acnt++] = &cip->attr_type.attr;
    363	cip->attr_gen[acnt++] = &cip->attr_val.attr;
    364	cip->attr_gen[acnt++] = &cip->attr_def.attr;
    365	cip->attr_val.show = show_val_norm;
    366	cip->attr_val.store = store_val_norm;
    367	if (pvr2_ctrl_has_custom_symbols(cptr)) {
    368		cip->attr_gen[acnt++] = &cip->attr_custom.attr;
    369		cip->attr_custom.show = show_val_custom;
    370		cip->attr_custom.store = store_val_custom;
    371	}
    372	switch (pvr2_ctrl_get_type(cptr)) {
    373	case pvr2_ctl_enum:
    374		// Control is an enumeration
    375		cip->attr_gen[acnt++] = &cip->attr_enum.attr;
    376		break;
    377	case pvr2_ctl_int:
    378		// Control is an integer
    379		cip->attr_gen[acnt++] = &cip->attr_min.attr;
    380		cip->attr_gen[acnt++] = &cip->attr_max.attr;
    381		break;
    382	case pvr2_ctl_bitmask:
    383		// Control is an bitmask
    384		cip->attr_gen[acnt++] = &cip->attr_bits.attr;
    385		break;
    386	default: break;
    387	}
    388
    389	cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
    390			pvr2_ctrl_get_name(cptr));
    391	cip->name[cnt] = 0;
    392	cip->grp.name = cip->name;
    393	cip->grp.attrs = cip->attr_gen;
    394
    395	ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
    396	if (ret) {
    397		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    398			   "sysfs_create_group error: %d",
    399			   ret);
    400		return;
    401	}
    402	cip->created_ok = !0;
    403}
    404
    405#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
    406static ssize_t debuginfo_show(struct device *, struct device_attribute *,
    407			      char *);
    408static ssize_t debugcmd_show(struct device *, struct device_attribute *,
    409			     char *);
    410static ssize_t debugcmd_store(struct device *, struct device_attribute *,
    411			      const char *, size_t count);
    412
    413static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
    414{
    415	struct pvr2_sysfs_debugifc *dip;
    416	int ret;
    417
    418	dip = kzalloc(sizeof(*dip),GFP_KERNEL);
    419	if (!dip) return;
    420	sysfs_attr_init(&dip->attr_debugcmd.attr);
    421	dip->attr_debugcmd.attr.name = "debugcmd";
    422	dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
    423	dip->attr_debugcmd.show = debugcmd_show;
    424	dip->attr_debugcmd.store = debugcmd_store;
    425	sysfs_attr_init(&dip->attr_debuginfo.attr);
    426	dip->attr_debuginfo.attr.name = "debuginfo";
    427	dip->attr_debuginfo.attr.mode = S_IRUGO;
    428	dip->attr_debuginfo.show = debuginfo_show;
    429	sfp->debugifc = dip;
    430	ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
    431	if (ret < 0) {
    432		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    433			   "device_create_file error: %d",
    434			   ret);
    435	} else {
    436		dip->debugcmd_created_ok = !0;
    437	}
    438	ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
    439	if (ret < 0) {
    440		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    441			   "device_create_file error: %d",
    442			   ret);
    443	} else {
    444		dip->debuginfo_created_ok = !0;
    445	}
    446}
    447
    448
    449static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
    450{
    451	if (!sfp->debugifc) return;
    452	if (sfp->debugifc->debuginfo_created_ok) {
    453		device_remove_file(sfp->class_dev,
    454					 &sfp->debugifc->attr_debuginfo);
    455	}
    456	if (sfp->debugifc->debugcmd_created_ok) {
    457		device_remove_file(sfp->class_dev,
    458					 &sfp->debugifc->attr_debugcmd);
    459	}
    460	kfree(sfp->debugifc);
    461	sfp->debugifc = NULL;
    462}
    463#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
    464
    465
    466static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
    467{
    468	unsigned int idx,cnt;
    469	cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
    470	for (idx = 0; idx < cnt; idx++) {
    471		pvr2_sysfs_add_control(sfp,idx);
    472	}
    473}
    474
    475
    476static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
    477{
    478	struct pvr2_sysfs_ctl_item *cip1,*cip2;
    479	for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
    480		cip2 = cip1->item_next;
    481		if (cip1->created_ok) {
    482			sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
    483		}
    484		pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
    485		kfree(cip1);
    486	}
    487}
    488
    489
    490static void pvr2_sysfs_class_release(struct class *class)
    491{
    492	struct pvr2_sysfs_class *clp;
    493	clp = container_of(class,struct pvr2_sysfs_class,class);
    494	pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
    495	kfree(clp);
    496}
    497
    498
    499static void pvr2_sysfs_release(struct device *class_dev)
    500{
    501	pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
    502	kfree(class_dev);
    503}
    504
    505
    506static void class_dev_destroy(struct pvr2_sysfs *sfp)
    507{
    508	struct device *dev;
    509	if (!sfp->class_dev) return;
    510#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
    511	pvr2_sysfs_tear_down_debugifc(sfp);
    512#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
    513	pvr2_sysfs_tear_down_controls(sfp);
    514	if (sfp->hdw_desc_created_ok) {
    515		device_remove_file(sfp->class_dev,
    516				   &sfp->attr_hdw_desc);
    517	}
    518	if (sfp->hdw_name_created_ok) {
    519		device_remove_file(sfp->class_dev,
    520				   &sfp->attr_hdw_name);
    521	}
    522	if (sfp->bus_info_created_ok) {
    523		device_remove_file(sfp->class_dev,
    524					 &sfp->attr_bus_info);
    525	}
    526	if (sfp->v4l_minor_number_created_ok) {
    527		device_remove_file(sfp->class_dev,
    528					 &sfp->attr_v4l_minor_number);
    529	}
    530	if (sfp->v4l_radio_minor_number_created_ok) {
    531		device_remove_file(sfp->class_dev,
    532					 &sfp->attr_v4l_radio_minor_number);
    533	}
    534	if (sfp->unit_number_created_ok) {
    535		device_remove_file(sfp->class_dev,
    536					 &sfp->attr_unit_number);
    537	}
    538	pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
    539	dev_set_drvdata(sfp->class_dev, NULL);
    540	dev = sfp->class_dev->parent;
    541	sfp->class_dev->parent = NULL;
    542	put_device(dev);
    543	device_unregister(sfp->class_dev);
    544	sfp->class_dev = NULL;
    545}
    546
    547
    548static ssize_t v4l_minor_number_show(struct device *class_dev,
    549				     struct device_attribute *attr, char *buf)
    550{
    551	struct pvr2_sysfs *sfp;
    552	sfp = dev_get_drvdata(class_dev);
    553	if (!sfp) return -EINVAL;
    554	return scnprintf(buf,PAGE_SIZE,"%d\n",
    555			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
    556						       pvr2_v4l_type_video));
    557}
    558
    559
    560static ssize_t bus_info_show(struct device *class_dev,
    561			     struct device_attribute *attr, char *buf)
    562{
    563	struct pvr2_sysfs *sfp;
    564	sfp = dev_get_drvdata(class_dev);
    565	if (!sfp) return -EINVAL;
    566	return scnprintf(buf,PAGE_SIZE,"%s\n",
    567			 pvr2_hdw_get_bus_info(sfp->channel.hdw));
    568}
    569
    570
    571static ssize_t hdw_name_show(struct device *class_dev,
    572			     struct device_attribute *attr, char *buf)
    573{
    574	struct pvr2_sysfs *sfp;
    575	sfp = dev_get_drvdata(class_dev);
    576	if (!sfp) return -EINVAL;
    577	return scnprintf(buf,PAGE_SIZE,"%s\n",
    578			 pvr2_hdw_get_type(sfp->channel.hdw));
    579}
    580
    581
    582static ssize_t hdw_desc_show(struct device *class_dev,
    583			     struct device_attribute *attr, char *buf)
    584{
    585	struct pvr2_sysfs *sfp;
    586	sfp = dev_get_drvdata(class_dev);
    587	if (!sfp) return -EINVAL;
    588	return scnprintf(buf,PAGE_SIZE,"%s\n",
    589			 pvr2_hdw_get_desc(sfp->channel.hdw));
    590}
    591
    592
    593static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
    594					   struct device_attribute *attr,
    595					   char *buf)
    596{
    597	struct pvr2_sysfs *sfp;
    598	sfp = dev_get_drvdata(class_dev);
    599	if (!sfp) return -EINVAL;
    600	return scnprintf(buf,PAGE_SIZE,"%d\n",
    601			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
    602						       pvr2_v4l_type_radio));
    603}
    604
    605
    606static ssize_t unit_number_show(struct device *class_dev,
    607				struct device_attribute *attr, char *buf)
    608{
    609	struct pvr2_sysfs *sfp;
    610	sfp = dev_get_drvdata(class_dev);
    611	if (!sfp) return -EINVAL;
    612	return scnprintf(buf,PAGE_SIZE,"%d\n",
    613			 pvr2_hdw_get_unit_number(sfp->channel.hdw));
    614}
    615
    616
    617static void class_dev_create(struct pvr2_sysfs *sfp,
    618			     struct pvr2_sysfs_class *class_ptr)
    619{
    620	struct usb_device *usb_dev;
    621	struct device *class_dev;
    622	int ret;
    623
    624	usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
    625	if (!usb_dev) return;
    626	class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
    627	if (!class_dev) return;
    628
    629	pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
    630
    631	class_dev->class = &class_ptr->class;
    632
    633	dev_set_name(class_dev, "%s",
    634		     pvr2_hdw_get_device_identifier(sfp->channel.hdw));
    635
    636	class_dev->parent = get_device(&usb_dev->dev);
    637
    638	sfp->class_dev = class_dev;
    639	dev_set_drvdata(class_dev, sfp);
    640	ret = device_register(class_dev);
    641	if (ret) {
    642		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    643			   "device_register failed");
    644		put_device(class_dev);
    645		return;
    646	}
    647
    648	sysfs_attr_init(&sfp->attr_v4l_minor_number.attr);
    649	sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
    650	sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
    651	sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
    652	sfp->attr_v4l_minor_number.store = NULL;
    653	ret = device_create_file(sfp->class_dev,
    654				       &sfp->attr_v4l_minor_number);
    655	if (ret < 0) {
    656		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    657			   "device_create_file error: %d",
    658			   ret);
    659	} else {
    660		sfp->v4l_minor_number_created_ok = !0;
    661	}
    662
    663	sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr);
    664	sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
    665	sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
    666	sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
    667	sfp->attr_v4l_radio_minor_number.store = NULL;
    668	ret = device_create_file(sfp->class_dev,
    669				       &sfp->attr_v4l_radio_minor_number);
    670	if (ret < 0) {
    671		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    672			   "device_create_file error: %d",
    673			   ret);
    674	} else {
    675		sfp->v4l_radio_minor_number_created_ok = !0;
    676	}
    677
    678	sysfs_attr_init(&sfp->attr_unit_number.attr);
    679	sfp->attr_unit_number.attr.name = "unit_number";
    680	sfp->attr_unit_number.attr.mode = S_IRUGO;
    681	sfp->attr_unit_number.show = unit_number_show;
    682	sfp->attr_unit_number.store = NULL;
    683	ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
    684	if (ret < 0) {
    685		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    686			   "device_create_file error: %d",
    687			   ret);
    688	} else {
    689		sfp->unit_number_created_ok = !0;
    690	}
    691
    692	sysfs_attr_init(&sfp->attr_bus_info.attr);
    693	sfp->attr_bus_info.attr.name = "bus_info_str";
    694	sfp->attr_bus_info.attr.mode = S_IRUGO;
    695	sfp->attr_bus_info.show = bus_info_show;
    696	sfp->attr_bus_info.store = NULL;
    697	ret = device_create_file(sfp->class_dev,
    698				       &sfp->attr_bus_info);
    699	if (ret < 0) {
    700		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    701			   "device_create_file error: %d",
    702			   ret);
    703	} else {
    704		sfp->bus_info_created_ok = !0;
    705	}
    706
    707	sysfs_attr_init(&sfp->attr_hdw_name.attr);
    708	sfp->attr_hdw_name.attr.name = "device_hardware_type";
    709	sfp->attr_hdw_name.attr.mode = S_IRUGO;
    710	sfp->attr_hdw_name.show = hdw_name_show;
    711	sfp->attr_hdw_name.store = NULL;
    712	ret = device_create_file(sfp->class_dev,
    713				 &sfp->attr_hdw_name);
    714	if (ret < 0) {
    715		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    716			   "device_create_file error: %d",
    717			   ret);
    718	} else {
    719		sfp->hdw_name_created_ok = !0;
    720	}
    721
    722	sysfs_attr_init(&sfp->attr_hdw_desc.attr);
    723	sfp->attr_hdw_desc.attr.name = "device_hardware_description";
    724	sfp->attr_hdw_desc.attr.mode = S_IRUGO;
    725	sfp->attr_hdw_desc.show = hdw_desc_show;
    726	sfp->attr_hdw_desc.store = NULL;
    727	ret = device_create_file(sfp->class_dev,
    728				 &sfp->attr_hdw_desc);
    729	if (ret < 0) {
    730		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
    731			   "device_create_file error: %d",
    732			   ret);
    733	} else {
    734		sfp->hdw_desc_created_ok = !0;
    735	}
    736
    737	pvr2_sysfs_add_controls(sfp);
    738#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
    739	pvr2_sysfs_add_debugifc(sfp);
    740#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
    741}
    742
    743
    744static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
    745{
    746	struct pvr2_sysfs *sfp;
    747	sfp = container_of(chp,struct pvr2_sysfs,channel);
    748	if (!sfp->channel.mc_head->disconnect_flag) return;
    749	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
    750	class_dev_destroy(sfp);
    751	pvr2_channel_done(&sfp->channel);
    752	kfree(sfp);
    753}
    754
    755
    756struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
    757				     struct pvr2_sysfs_class *class_ptr)
    758{
    759	struct pvr2_sysfs *sfp;
    760	sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
    761	if (!sfp) return sfp;
    762	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
    763	pvr2_channel_init(&sfp->channel,mp);
    764	sfp->channel.check_func = pvr2_sysfs_internal_check;
    765
    766	class_dev_create(sfp,class_ptr);
    767	return sfp;
    768}
    769
    770
    771
    772struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
    773{
    774	struct pvr2_sysfs_class *clp;
    775	clp = kzalloc(sizeof(*clp),GFP_KERNEL);
    776	if (!clp) return clp;
    777	pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
    778			 clp);
    779	clp->class.name = "pvrusb2";
    780	clp->class.class_release = pvr2_sysfs_class_release;
    781	clp->class.dev_release = pvr2_sysfs_release;
    782	if (class_register(&clp->class)) {
    783		pvr2_sysfs_trace(
    784			"Registration failed for pvr2_sysfs_class id=%p",clp);
    785		kfree(clp);
    786		clp = NULL;
    787	}
    788	return clp;
    789}
    790
    791
    792void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
    793{
    794	pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
    795	if (clp)
    796		class_unregister(&clp->class);
    797}
    798
    799
    800#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
    801static ssize_t debuginfo_show(struct device *class_dev,
    802			      struct device_attribute *attr, char *buf)
    803{
    804	struct pvr2_sysfs *sfp;
    805	sfp = dev_get_drvdata(class_dev);
    806	if (!sfp) return -EINVAL;
    807	pvr2_hdw_trigger_module_log(sfp->channel.hdw);
    808	return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
    809}
    810
    811
    812static ssize_t debugcmd_show(struct device *class_dev,
    813			     struct device_attribute *attr, char *buf)
    814{
    815	struct pvr2_sysfs *sfp;
    816	sfp = dev_get_drvdata(class_dev);
    817	if (!sfp) return -EINVAL;
    818	return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
    819}
    820
    821
    822static ssize_t debugcmd_store(struct device *class_dev,
    823			      struct device_attribute *attr,
    824			      const char *buf, size_t count)
    825{
    826	struct pvr2_sysfs *sfp;
    827	int ret;
    828
    829	sfp = dev_get_drvdata(class_dev);
    830	if (!sfp) return -EINVAL;
    831
    832	ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
    833	if (ret < 0) return ret;
    834	return count;
    835}
    836#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */