xref: /linux/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c (revision e7d759f31ca295d589f7420719c311870bb3166f)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
769 void pvr2_sysfs_class_destroy(void)
770 {
771 	class_unregister(&pvr2_class);
772 }
773 
774 
775 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
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 
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 
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