5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/string.h>
23 #include <linux/slab.h>
24 #include <asm/semaphore.h>
25 #include "pvrusb2-sysfs.h"
26 #include "pvrusb2-hdw.h"
27 #include "pvrusb2-debug.h"
28 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
29 #include "pvrusb2-debugifc.h"
30 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
32 #define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
35 struct pvr2_channel channel
;
36 struct device
*class_dev
;
37 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
38 struct pvr2_sysfs_debugifc
*debugifc
;
39 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
40 struct pvr2_sysfs_ctl_item
*item_first
;
41 struct pvr2_sysfs_ctl_item
*item_last
;
42 struct device_attribute attr_v4l_minor_number
;
43 struct device_attribute attr_v4l_radio_minor_number
;
44 struct device_attribute attr_unit_number
;
45 struct device_attribute attr_bus_info
;
46 struct device_attribute attr_hdw_name
;
47 struct device_attribute attr_hdw_desc
;
48 int v4l_minor_number_created_ok
;
49 int v4l_radio_minor_number_created_ok
;
50 int unit_number_created_ok
;
51 int bus_info_created_ok
;
52 int hdw_name_created_ok
;
53 int hdw_desc_created_ok
;
56 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
57 struct pvr2_sysfs_debugifc
{
58 struct device_attribute attr_debugcmd
;
59 struct device_attribute attr_debuginfo
;
60 int debugcmd_created_ok
;
61 int debuginfo_created_ok
;
63 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
65 struct pvr2_sysfs_ctl_item
{
66 struct device_attribute attr_name
;
67 struct device_attribute attr_type
;
68 struct device_attribute attr_min
;
69 struct device_attribute attr_max
;
70 struct device_attribute attr_enum
;
71 struct device_attribute attr_bits
;
72 struct device_attribute attr_val
;
73 struct device_attribute attr_custom
;
74 struct pvr2_ctrl
*cptr
;
75 struct pvr2_sysfs
*chptr
;
76 struct pvr2_sysfs_ctl_item
*item_next
;
77 struct attribute
*attr_gen
[7];
78 struct attribute_group grp
;
83 struct pvr2_sysfs_class
{
87 static ssize_t
show_name(int id
,struct device
*class_dev
,char *buf
)
89 struct pvr2_ctrl
*cptr
;
90 struct pvr2_sysfs
*sfp
;
93 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
94 if (!sfp
) return -EINVAL
;
95 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
96 if (!cptr
) return -EINVAL
;
98 name
= pvr2_ctrl_get_desc(cptr
);
99 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp
,id
,name
);
101 if (!name
) return -EINVAL
;
103 return scnprintf(buf
,PAGE_SIZE
,"%s\n",name
);
106 static ssize_t
show_type(int id
,struct device
*class_dev
,char *buf
)
108 struct pvr2_ctrl
*cptr
;
109 struct pvr2_sysfs
*sfp
;
111 enum pvr2_ctl_type tp
;
113 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
114 if (!sfp
) return -EINVAL
;
115 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
116 if (!cptr
) return -EINVAL
;
118 tp
= pvr2_ctrl_get_type(cptr
);
120 case pvr2_ctl_int
: name
= "integer"; break;
121 case pvr2_ctl_enum
: name
= "enum"; break;
122 case pvr2_ctl_bitmask
: name
= "bitmask"; break;
123 case pvr2_ctl_bool
: name
= "boolean"; break;
124 default: name
= "?"; break;
126 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp
,id
,name
);
128 if (!name
) return -EINVAL
;
130 return scnprintf(buf
,PAGE_SIZE
,"%s\n",name
);
133 static ssize_t
show_min(int id
,struct device
*class_dev
,char *buf
)
135 struct pvr2_ctrl
*cptr
;
136 struct pvr2_sysfs
*sfp
;
139 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
140 if (!sfp
) return -EINVAL
;
141 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
142 if (!cptr
) return -EINVAL
;
143 val
= pvr2_ctrl_get_min(cptr
);
145 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp
,id
,val
);
147 return scnprintf(buf
,PAGE_SIZE
,"%ld\n",val
);
150 static ssize_t
show_max(int id
,struct device
*class_dev
,char *buf
)
152 struct pvr2_ctrl
*cptr
;
153 struct pvr2_sysfs
*sfp
;
156 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
157 if (!sfp
) return -EINVAL
;
158 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
159 if (!cptr
) return -EINVAL
;
160 val
= pvr2_ctrl_get_max(cptr
);
162 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp
,id
,val
);
164 return scnprintf(buf
,PAGE_SIZE
,"%ld\n",val
);
167 static ssize_t
show_val_norm(int id
,struct device
*class_dev
,char *buf
)
169 struct pvr2_ctrl
*cptr
;
170 struct pvr2_sysfs
*sfp
;
172 unsigned int cnt
= 0;
174 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
175 if (!sfp
) return -EINVAL
;
176 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
177 if (!cptr
) return -EINVAL
;
179 ret
= pvr2_ctrl_get_value(cptr
,&val
);
180 if (ret
< 0) return ret
;
182 ret
= pvr2_ctrl_value_to_sym(cptr
,~0,val
,
183 buf
,PAGE_SIZE
-1,&cnt
);
185 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
191 static ssize_t
show_val_custom(int id
,struct device
*class_dev
,char *buf
)
193 struct pvr2_ctrl
*cptr
;
194 struct pvr2_sysfs
*sfp
;
196 unsigned int cnt
= 0;
198 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
199 if (!sfp
) return -EINVAL
;
200 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
201 if (!cptr
) return -EINVAL
;
203 ret
= pvr2_ctrl_get_value(cptr
,&val
);
204 if (ret
< 0) return ret
;
206 ret
= pvr2_ctrl_custom_value_to_sym(cptr
,~0,val
,
207 buf
,PAGE_SIZE
-1,&cnt
);
209 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
215 static ssize_t
show_enum(int id
,struct device
*class_dev
,char *buf
)
217 struct pvr2_ctrl
*cptr
;
218 struct pvr2_sysfs
*sfp
;
220 unsigned int bcnt
,ccnt
,ecnt
;
222 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
223 if (!sfp
) return -EINVAL
;
224 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
225 if (!cptr
) return -EINVAL
;
226 ecnt
= pvr2_ctrl_get_cnt(cptr
);
228 for (val
= 0; val
< ecnt
; val
++) {
229 pvr2_ctrl_get_valname(cptr
,val
,buf
+bcnt
,PAGE_SIZE
-bcnt
,&ccnt
);
232 if (bcnt
>= PAGE_SIZE
) break;
236 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp
,id
);
240 static ssize_t
show_bits(int id
,struct device
*class_dev
,char *buf
)
242 struct pvr2_ctrl
*cptr
;
243 struct pvr2_sysfs
*sfp
;
245 unsigned int bcnt
,ccnt
;
247 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
248 if (!sfp
) return -EINVAL
;
249 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
250 if (!cptr
) return -EINVAL
;
251 valid_bits
= pvr2_ctrl_get_mask(cptr
);
253 for (msk
= 1; valid_bits
; msk
<<= 1) {
254 if (!(msk
& valid_bits
)) continue;
256 pvr2_ctrl_get_valname(cptr
,msk
,buf
+bcnt
,PAGE_SIZE
-bcnt
,&ccnt
);
258 if (bcnt
>= PAGE_SIZE
) break;
262 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp
,id
);
266 static int store_val_any(int id
,int customfl
,struct pvr2_sysfs
*sfp
,
267 const char *buf
,unsigned int count
)
269 struct pvr2_ctrl
*cptr
;
273 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
275 ret
= pvr2_ctrl_custom_sym_to_value(cptr
,buf
,count
,&mask
,&val
);
277 ret
= pvr2_ctrl_sym_to_value(cptr
,buf
,count
,&mask
,&val
);
279 if (ret
< 0) return ret
;
280 ret
= pvr2_ctrl_set_mask_value(cptr
,mask
,val
);
281 pvr2_hdw_commit_ctl(sfp
->channel
.hdw
);
285 static ssize_t
store_val_norm(int id
,struct device
*class_dev
,
286 const char *buf
,size_t count
)
288 struct pvr2_sysfs
*sfp
;
290 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
291 ret
= store_val_any(id
,0,sfp
,buf
,count
);
292 if (!ret
) ret
= count
;
296 static ssize_t
store_val_custom(int id
,struct device
*class_dev
,
297 const char *buf
,size_t count
)
299 struct pvr2_sysfs
*sfp
;
301 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
302 ret
= store_val_any(id
,1,sfp
,buf
,count
);
303 if (!ret
) ret
= count
;
308 Mike Isely <isely@pobox.com> 30-April-2005
310 This next batch of horrible preprocessor hackery is needed because the
311 kernel's device_attribute mechanism fails to pass the actual
312 attribute through to the show / store functions, which means we have no
313 way to package up any attribute-specific parameters, like for example the
314 control id. So we work around this brain-damage by encoding the control
315 id into the show / store functions themselves and pick the function based
316 on the control id we're setting up. These macros try to ease the pain.
320 #define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
321 static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
322 struct device_attribute *attr, char *buf) \
323 { return sf_name(ctl_id,class_dev,buf); }
325 #define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
326 static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
327 struct device_attribute *attr, const char *buf, size_t count) \
328 { return sf_name(ctl_id,class_dev,buf,count); }
330 #define CREATE_BATCH(ctl_id) \
331 CREATE_SHOW_INSTANCE(show_name,ctl_id) \
332 CREATE_SHOW_INSTANCE(show_type,ctl_id) \
333 CREATE_SHOW_INSTANCE(show_min,ctl_id) \
334 CREATE_SHOW_INSTANCE(show_max,ctl_id) \
335 CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
336 CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
337 CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
338 CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
339 CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
340 CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
403 struct pvr2_sysfs_func_set
{
404 ssize_t (*show_name
)(struct device
*,
405 struct device_attribute
*attr
, char *);
406 ssize_t (*show_type
)(struct device
*,
407 struct device_attribute
*attr
, char *);
408 ssize_t (*show_min
)(struct device
*,
409 struct device_attribute
*attr
, char *);
410 ssize_t (*show_max
)(struct device
*,
411 struct device_attribute
*attr
, char *);
412 ssize_t (*show_enum
)(struct device
*,
413 struct device_attribute
*attr
, char *);
414 ssize_t (*show_bits
)(struct device
*,
415 struct device_attribute
*attr
, char *);
416 ssize_t (*show_val_norm
)(struct device
*,
417 struct device_attribute
*attr
, char *);
418 ssize_t (*store_val_norm
)(struct device
*,
419 struct device_attribute
*attr
,
420 const char *,size_t);
421 ssize_t (*show_val_custom
)(struct device
*,
422 struct device_attribute
*attr
, char *);
423 ssize_t (*store_val_custom
)(struct device
*,
424 struct device_attribute
*attr
,
425 const char *,size_t);
428 #define INIT_BATCH(ctl_id) \
430 .show_name = show_name_##ctl_id, \
431 .show_type = show_type_##ctl_id, \
432 .show_min = show_min_##ctl_id, \
433 .show_max = show_max_##ctl_id, \
434 .show_enum = show_enum_##ctl_id, \
435 .show_bits = show_bits_##ctl_id, \
436 .show_val_norm = show_val_norm_##ctl_id, \
437 .store_val_norm = store_val_norm_##ctl_id, \
438 .show_val_custom = show_val_custom_##ctl_id, \
439 .store_val_custom = store_val_custom_##ctl_id, \
442 static struct pvr2_sysfs_func_set funcs[] = {
506 static void pvr2_sysfs_add_control(struct pvr2_sysfs
*sfp
,int ctl_id
)
508 struct pvr2_sysfs_ctl_item
*cip
;
509 struct pvr2_sysfs_func_set
*fp
;
510 struct pvr2_ctrl
*cptr
;
511 unsigned int cnt
,acnt
;
514 if ((ctl_id
< 0) || (ctl_id
>= ARRAY_SIZE(funcs
))) {
519 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,ctl_id
);
522 cip
= kzalloc(sizeof(*cip
),GFP_KERNEL
);
524 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip
);
529 cip
->item_next
= NULL
;
530 if (sfp
->item_last
) {
531 sfp
->item_last
->item_next
= cip
;
533 sfp
->item_first
= cip
;
535 sfp
->item_last
= cip
;
537 cip
->attr_name
.attr
.name
= "name";
538 cip
->attr_name
.attr
.mode
= S_IRUGO
;
539 cip
->attr_name
.show
= fp
->show_name
;
541 cip
->attr_type
.attr
.name
= "type";
542 cip
->attr_type
.attr
.mode
= S_IRUGO
;
543 cip
->attr_type
.show
= fp
->show_type
;
545 cip
->attr_min
.attr
.name
= "min_val";
546 cip
->attr_min
.attr
.mode
= S_IRUGO
;
547 cip
->attr_min
.show
= fp
->show_min
;
549 cip
->attr_max
.attr
.name
= "max_val";
550 cip
->attr_max
.attr
.mode
= S_IRUGO
;
551 cip
->attr_max
.show
= fp
->show_max
;
553 cip
->attr_val
.attr
.name
= "cur_val";
554 cip
->attr_val
.attr
.mode
= S_IRUGO
;
556 cip
->attr_custom
.attr
.name
= "custom_val";
557 cip
->attr_custom
.attr
.mode
= S_IRUGO
;
559 cip
->attr_enum
.attr
.name
= "enum_val";
560 cip
->attr_enum
.attr
.mode
= S_IRUGO
;
561 cip
->attr_enum
.show
= fp
->show_enum
;
563 cip
->attr_bits
.attr
.name
= "bit_val";
564 cip
->attr_bits
.attr
.mode
= S_IRUGO
;
565 cip
->attr_bits
.show
= fp
->show_bits
;
567 if (pvr2_ctrl_is_writable(cptr
)) {
568 cip
->attr_val
.attr
.mode
|= S_IWUSR
|S_IWGRP
;
569 cip
->attr_custom
.attr
.mode
|= S_IWUSR
|S_IWGRP
;
573 cip
->attr_gen
[acnt
++] = &cip
->attr_name
.attr
;
574 cip
->attr_gen
[acnt
++] = &cip
->attr_type
.attr
;
575 cip
->attr_gen
[acnt
++] = &cip
->attr_val
.attr
;
576 cip
->attr_val
.show
= fp
->show_val_norm
;
577 cip
->attr_val
.store
= fp
->store_val_norm
;
578 if (pvr2_ctrl_has_custom_symbols(cptr
)) {
579 cip
->attr_gen
[acnt
++] = &cip
->attr_custom
.attr
;
580 cip
->attr_custom
.show
= fp
->show_val_custom
;
581 cip
->attr_custom
.store
= fp
->store_val_custom
;
583 switch (pvr2_ctrl_get_type(cptr
)) {
585 // Control is an enumeration
586 cip
->attr_gen
[acnt
++] = &cip
->attr_enum
.attr
;
589 // Control is an integer
590 cip
->attr_gen
[acnt
++] = &cip
->attr_min
.attr
;
591 cip
->attr_gen
[acnt
++] = &cip
->attr_max
.attr
;
593 case pvr2_ctl_bitmask
:
594 // Control is an bitmask
595 cip
->attr_gen
[acnt
++] = &cip
->attr_bits
.attr
;
600 cnt
= scnprintf(cip
->name
,sizeof(cip
->name
)-1,"ctl_%s",
601 pvr2_ctrl_get_name(cptr
));
603 cip
->grp
.name
= cip
->name
;
604 cip
->grp
.attrs
= cip
->attr_gen
;
606 ret
= sysfs_create_group(&sfp
->class_dev
->kobj
,&cip
->grp
);
608 printk(KERN_WARNING
"%s: sysfs_create_group error: %d\n",
612 cip
->created_ok
= !0;
615 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
616 static ssize_t
debuginfo_show(struct device
*, struct device_attribute
*,
618 static ssize_t
debugcmd_show(struct device
*, struct device_attribute
*,
620 static ssize_t
debugcmd_store(struct device
*, struct device_attribute
*,
621 const char *, size_t count
);
623 static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs
*sfp
)
625 struct pvr2_sysfs_debugifc
*dip
;
628 dip
= kzalloc(sizeof(*dip
),GFP_KERNEL
);
630 dip
->attr_debugcmd
.attr
.name
= "debugcmd";
631 dip
->attr_debugcmd
.attr
.mode
= S_IRUGO
|S_IWUSR
|S_IWGRP
;
632 dip
->attr_debugcmd
.show
= debugcmd_show
;
633 dip
->attr_debugcmd
.store
= debugcmd_store
;
634 dip
->attr_debuginfo
.attr
.name
= "debuginfo";
635 dip
->attr_debuginfo
.attr
.mode
= S_IRUGO
;
636 dip
->attr_debuginfo
.show
= debuginfo_show
;
638 ret
= device_create_file(sfp
->class_dev
,&dip
->attr_debugcmd
);
640 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
643 dip
->debugcmd_created_ok
= !0;
645 ret
= device_create_file(sfp
->class_dev
,&dip
->attr_debuginfo
);
647 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
650 dip
->debuginfo_created_ok
= !0;
655 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs
*sfp
)
657 if (!sfp
->debugifc
) return;
658 if (sfp
->debugifc
->debuginfo_created_ok
) {
659 device_remove_file(sfp
->class_dev
,
660 &sfp
->debugifc
->attr_debuginfo
);
662 if (sfp
->debugifc
->debugcmd_created_ok
) {
663 device_remove_file(sfp
->class_dev
,
664 &sfp
->debugifc
->attr_debugcmd
);
666 kfree(sfp
->debugifc
);
667 sfp
->debugifc
= NULL
;
669 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
672 static void pvr2_sysfs_add_controls(struct pvr2_sysfs
*sfp
)
674 unsigned int idx
,cnt
;
675 cnt
= pvr2_hdw_get_ctrl_count(sfp
->channel
.hdw
);
676 for (idx
= 0; idx
< cnt
; idx
++) {
677 pvr2_sysfs_add_control(sfp
,idx
);
682 static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs
*sfp
)
684 struct pvr2_sysfs_ctl_item
*cip1
,*cip2
;
685 for (cip1
= sfp
->item_first
; cip1
; cip1
= cip2
) {
686 cip2
= cip1
->item_next
;
687 if (cip1
->created_ok
) {
688 sysfs_remove_group(&sfp
->class_dev
->kobj
,&cip1
->grp
);
690 pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1
);
696 static void pvr2_sysfs_class_release(struct class *class)
698 struct pvr2_sysfs_class
*clp
;
699 clp
= container_of(class,struct pvr2_sysfs_class
,class);
700 pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp
);
705 static void pvr2_sysfs_release(struct device
*class_dev
)
707 pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev
);
712 static void class_dev_destroy(struct pvr2_sysfs
*sfp
)
714 if (!sfp
->class_dev
) return;
715 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
716 pvr2_sysfs_tear_down_debugifc(sfp
);
717 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
718 pvr2_sysfs_tear_down_controls(sfp
);
719 if (sfp
->hdw_desc_created_ok
) {
720 device_remove_file(sfp
->class_dev
,
721 &sfp
->attr_hdw_desc
);
723 if (sfp
->hdw_name_created_ok
) {
724 device_remove_file(sfp
->class_dev
,
725 &sfp
->attr_hdw_name
);
727 if (sfp
->bus_info_created_ok
) {
728 device_remove_file(sfp
->class_dev
,
729 &sfp
->attr_bus_info
);
731 if (sfp
->v4l_minor_number_created_ok
) {
732 device_remove_file(sfp
->class_dev
,
733 &sfp
->attr_v4l_minor_number
);
735 if (sfp
->v4l_radio_minor_number_created_ok
) {
736 device_remove_file(sfp
->class_dev
,
737 &sfp
->attr_v4l_radio_minor_number
);
739 if (sfp
->unit_number_created_ok
) {
740 device_remove_file(sfp
->class_dev
,
741 &sfp
->attr_unit_number
);
743 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp
->class_dev
);
744 sfp
->class_dev
->driver_data
= NULL
;
745 device_unregister(sfp
->class_dev
);
746 sfp
->class_dev
= NULL
;
750 static ssize_t
v4l_minor_number_show(struct device
*class_dev
,
751 struct device_attribute
*attr
, char *buf
)
753 struct pvr2_sysfs
*sfp
;
754 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
755 if (!sfp
) return -EINVAL
;
756 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
757 pvr2_hdw_v4l_get_minor_number(sfp
->channel
.hdw
,
758 pvr2_v4l_type_video
));
762 static ssize_t
bus_info_show(struct device
*class_dev
,
763 struct device_attribute
*attr
, char *buf
)
765 struct pvr2_sysfs
*sfp
;
766 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
767 if (!sfp
) return -EINVAL
;
768 return scnprintf(buf
,PAGE_SIZE
,"%s\n",
769 pvr2_hdw_get_bus_info(sfp
->channel
.hdw
));
773 static ssize_t
hdw_name_show(struct device
*class_dev
,
774 struct device_attribute
*attr
, char *buf
)
776 struct pvr2_sysfs
*sfp
;
777 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
778 if (!sfp
) return -EINVAL
;
779 return scnprintf(buf
,PAGE_SIZE
,"%s\n",
780 pvr2_hdw_get_type(sfp
->channel
.hdw
));
784 static ssize_t
hdw_desc_show(struct device
*class_dev
,
785 struct device_attribute
*attr
, char *buf
)
787 struct pvr2_sysfs
*sfp
;
788 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
789 if (!sfp
) return -EINVAL
;
790 return scnprintf(buf
,PAGE_SIZE
,"%s\n",
791 pvr2_hdw_get_desc(sfp
->channel
.hdw
));
795 static ssize_t
v4l_radio_minor_number_show(struct device
*class_dev
,
796 struct device_attribute
*attr
,
799 struct pvr2_sysfs
*sfp
;
800 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
801 if (!sfp
) return -EINVAL
;
802 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
803 pvr2_hdw_v4l_get_minor_number(sfp
->channel
.hdw
,
804 pvr2_v4l_type_radio
));
808 static ssize_t
unit_number_show(struct device
*class_dev
,
809 struct device_attribute
*attr
, char *buf
)
811 struct pvr2_sysfs
*sfp
;
812 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
813 if (!sfp
) return -EINVAL
;
814 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
815 pvr2_hdw_get_unit_number(sfp
->channel
.hdw
));
819 static void class_dev_create(struct pvr2_sysfs
*sfp
,
820 struct pvr2_sysfs_class
*class_ptr
)
822 struct usb_device
*usb_dev
;
823 struct device
*class_dev
;
826 usb_dev
= pvr2_hdw_get_dev(sfp
->channel
.hdw
);
827 if (!usb_dev
) return;
828 class_dev
= kzalloc(sizeof(*class_dev
),GFP_KERNEL
);
829 if (!class_dev
) return;
831 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev
);
833 class_dev
->class = &class_ptr
->class;
834 if (pvr2_hdw_get_sn(sfp
->channel
.hdw
)) {
835 snprintf(class_dev
->bus_id
, BUS_ID_SIZE
, "sn-%lu",
836 pvr2_hdw_get_sn(sfp
->channel
.hdw
));
837 } else if (pvr2_hdw_get_unit_number(sfp
->channel
.hdw
) >= 0) {
838 snprintf(class_dev
->bus_id
, BUS_ID_SIZE
, "unit-%c",
839 pvr2_hdw_get_unit_number(sfp
->channel
.hdw
) + 'a');
845 class_dev
->parent
= &usb_dev
->dev
;
847 sfp
->class_dev
= class_dev
;
848 class_dev
->driver_data
= sfp
;
849 ret
= device_register(class_dev
);
851 printk(KERN_ERR
"%s: device_register failed\n",
857 sfp
->attr_v4l_minor_number
.attr
.name
= "v4l_minor_number";
858 sfp
->attr_v4l_minor_number
.attr
.mode
= S_IRUGO
;
859 sfp
->attr_v4l_minor_number
.show
= v4l_minor_number_show
;
860 sfp
->attr_v4l_minor_number
.store
= NULL
;
861 ret
= device_create_file(sfp
->class_dev
,
862 &sfp
->attr_v4l_minor_number
);
864 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
867 sfp
->v4l_minor_number_created_ok
= !0;
870 sfp
->attr_v4l_radio_minor_number
.attr
.name
= "v4l_radio_minor_number";
871 sfp
->attr_v4l_radio_minor_number
.attr
.mode
= S_IRUGO
;
872 sfp
->attr_v4l_radio_minor_number
.show
= v4l_radio_minor_number_show
;
873 sfp
->attr_v4l_radio_minor_number
.store
= NULL
;
874 ret
= device_create_file(sfp
->class_dev
,
875 &sfp
->attr_v4l_radio_minor_number
);
877 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
880 sfp
->v4l_radio_minor_number_created_ok
= !0;
883 sfp
->attr_unit_number
.attr
.name
= "unit_number";
884 sfp
->attr_unit_number
.attr
.mode
= S_IRUGO
;
885 sfp
->attr_unit_number
.show
= unit_number_show
;
886 sfp
->attr_unit_number
.store
= NULL
;
887 ret
= device_create_file(sfp
->class_dev
,&sfp
->attr_unit_number
);
889 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
892 sfp
->unit_number_created_ok
= !0;
895 sfp
->attr_bus_info
.attr
.name
= "bus_info_str";
896 sfp
->attr_bus_info
.attr
.mode
= S_IRUGO
;
897 sfp
->attr_bus_info
.show
= bus_info_show
;
898 sfp
->attr_bus_info
.store
= NULL
;
899 ret
= device_create_file(sfp
->class_dev
,
900 &sfp
->attr_bus_info
);
902 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
905 sfp
->bus_info_created_ok
= !0;
908 sfp
->attr_hdw_name
.attr
.name
= "device_hardware_type";
909 sfp
->attr_hdw_name
.attr
.mode
= S_IRUGO
;
910 sfp
->attr_hdw_name
.show
= hdw_name_show
;
911 sfp
->attr_hdw_name
.store
= NULL
;
912 ret
= device_create_file(sfp
->class_dev
,
913 &sfp
->attr_hdw_name
);
915 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
918 sfp
->hdw_name_created_ok
= !0;
921 sfp
->attr_hdw_desc
.attr
.name
= "device_hardware_description";
922 sfp
->attr_hdw_desc
.attr
.mode
= S_IRUGO
;
923 sfp
->attr_hdw_desc
.show
= hdw_desc_show
;
924 sfp
->attr_hdw_desc
.store
= NULL
;
925 ret
= device_create_file(sfp
->class_dev
,
926 &sfp
->attr_hdw_desc
);
928 printk(KERN_WARNING
"%s: device_create_file error: %d\n",
931 sfp
->hdw_desc_created_ok
= !0;
934 pvr2_sysfs_add_controls(sfp
);
935 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
936 pvr2_sysfs_add_debugifc(sfp
);
937 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
941 static void pvr2_sysfs_internal_check(struct pvr2_channel
*chp
)
943 struct pvr2_sysfs
*sfp
;
944 sfp
= container_of(chp
,struct pvr2_sysfs
,channel
);
945 if (!sfp
->channel
.mc_head
->disconnect_flag
) return;
946 pvr2_trace(PVR2_TRACE_STRUCT
,"Destroying pvr2_sysfs id=%p",sfp
);
947 class_dev_destroy(sfp
);
948 pvr2_channel_done(&sfp
->channel
);
953 struct pvr2_sysfs
*pvr2_sysfs_create(struct pvr2_context
*mp
,
954 struct pvr2_sysfs_class
*class_ptr
)
956 struct pvr2_sysfs
*sfp
;
957 sfp
= kzalloc(sizeof(*sfp
),GFP_KERNEL
);
958 if (!sfp
) return sfp
;
959 pvr2_trace(PVR2_TRACE_STRUCT
,"Creating pvr2_sysfs id=%p",sfp
);
960 pvr2_channel_init(&sfp
->channel
,mp
);
961 sfp
->channel
.check_func
= pvr2_sysfs_internal_check
;
963 class_dev_create(sfp
,class_ptr
);
969 struct pvr2_sysfs_class
*pvr2_sysfs_class_create(void)
971 struct pvr2_sysfs_class
*clp
;
972 clp
= kzalloc(sizeof(*clp
),GFP_KERNEL
);
973 if (!clp
) return clp
;
974 pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp
);
975 clp
->class.name
= "pvrusb2";
976 clp
->class.class_release
= pvr2_sysfs_class_release
;
977 clp
->class.dev_release
= pvr2_sysfs_release
;
978 if (class_register(&clp
->class)) {
980 "Registration failed for pvr2_sysfs_class id=%p",clp
);
988 void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class
*clp
)
990 class_unregister(&clp
->class);
994 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
995 static ssize_t
debuginfo_show(struct device
*class_dev
,
996 struct device_attribute
*attr
, char *buf
)
998 struct pvr2_sysfs
*sfp
;
999 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
1000 if (!sfp
) return -EINVAL
;
1001 pvr2_hdw_trigger_module_log(sfp
->channel
.hdw
);
1002 return pvr2_debugifc_print_info(sfp
->channel
.hdw
,buf
,PAGE_SIZE
);
1006 static ssize_t
debugcmd_show(struct device
*class_dev
,
1007 struct device_attribute
*attr
, char *buf
)
1009 struct pvr2_sysfs
*sfp
;
1010 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
1011 if (!sfp
) return -EINVAL
;
1012 return pvr2_debugifc_print_status(sfp
->channel
.hdw
,buf
,PAGE_SIZE
);
1016 static ssize_t
debugcmd_store(struct device
*class_dev
,
1017 struct device_attribute
*attr
,
1018 const char *buf
, size_t count
)
1020 struct pvr2_sysfs
*sfp
;
1023 sfp
= (struct pvr2_sysfs
*)class_dev
->driver_data
;
1024 if (!sfp
) return -EINVAL
;
1026 ret
= pvr2_debugifc_docmd(sfp
->channel
.hdw
,buf
,count
);
1027 if (ret
< 0) return ret
;
1030 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
1034 Stuff for Emacs to see, in order to encourage consistent editing style:
1035 *** Local Variables: ***
1037 *** fill-column: 75 ***
1038 *** tab-width: 8 ***
1039 *** c-basic-offset: 8 ***