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