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 class_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 class_device_attribute attr_v4l_minor_number
;
43 struct class_device_attribute attr_v4l_radio_minor_number
;
44 struct class_device_attribute attr_unit_number
;
45 int v4l_minor_number_created_ok
;
46 int v4l_radio_minor_number_created_ok
;
47 int unit_number_created_ok
;
50 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
51 struct pvr2_sysfs_debugifc
{
52 struct class_device_attribute attr_debugcmd
;
53 struct class_device_attribute attr_debuginfo
;
54 int debugcmd_created_ok
;
55 int debuginfo_created_ok
;
57 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
59 struct pvr2_sysfs_ctl_item
{
60 struct class_device_attribute attr_name
;
61 struct class_device_attribute attr_type
;
62 struct class_device_attribute attr_min
;
63 struct class_device_attribute attr_max
;
64 struct class_device_attribute attr_enum
;
65 struct class_device_attribute attr_bits
;
66 struct class_device_attribute attr_val
;
67 struct class_device_attribute attr_custom
;
68 struct pvr2_ctrl
*cptr
;
69 struct pvr2_sysfs
*chptr
;
70 struct pvr2_sysfs_ctl_item
*item_next
;
71 struct attribute
*attr_gen
[7];
72 struct attribute_group grp
;
77 struct pvr2_sysfs_class
{
81 static ssize_t
show_name(int id
,struct class_device
*class_dev
,char *buf
)
83 struct pvr2_ctrl
*cptr
;
84 struct pvr2_sysfs
*sfp
;
87 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
88 if (!sfp
) return -EINVAL
;
89 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
90 if (!cptr
) return -EINVAL
;
92 name
= pvr2_ctrl_get_desc(cptr
);
93 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp
,id
,name
);
95 if (!name
) return -EINVAL
;
97 return scnprintf(buf
,PAGE_SIZE
,"%s\n",name
);
100 static ssize_t
show_type(int id
,struct class_device
*class_dev
,char *buf
)
102 struct pvr2_ctrl
*cptr
;
103 struct pvr2_sysfs
*sfp
;
105 enum pvr2_ctl_type tp
;
107 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
108 if (!sfp
) return -EINVAL
;
109 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
110 if (!cptr
) return -EINVAL
;
112 tp
= pvr2_ctrl_get_type(cptr
);
114 case pvr2_ctl_int
: name
= "integer"; break;
115 case pvr2_ctl_enum
: name
= "enum"; break;
116 case pvr2_ctl_bitmask
: name
= "bitmask"; break;
117 case pvr2_ctl_bool
: name
= "boolean"; break;
118 default: name
= "?"; break;
120 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp
,id
,name
);
122 if (!name
) return -EINVAL
;
124 return scnprintf(buf
,PAGE_SIZE
,"%s\n",name
);
127 static ssize_t
show_min(int id
,struct class_device
*class_dev
,char *buf
)
129 struct pvr2_ctrl
*cptr
;
130 struct pvr2_sysfs
*sfp
;
133 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
134 if (!sfp
) return -EINVAL
;
135 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
136 if (!cptr
) return -EINVAL
;
137 val
= pvr2_ctrl_get_min(cptr
);
139 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp
,id
,val
);
141 return scnprintf(buf
,PAGE_SIZE
,"%ld\n",val
);
144 static ssize_t
show_max(int id
,struct class_device
*class_dev
,char *buf
)
146 struct pvr2_ctrl
*cptr
;
147 struct pvr2_sysfs
*sfp
;
150 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
151 if (!sfp
) return -EINVAL
;
152 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
153 if (!cptr
) return -EINVAL
;
154 val
= pvr2_ctrl_get_max(cptr
);
156 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp
,id
,val
);
158 return scnprintf(buf
,PAGE_SIZE
,"%ld\n",val
);
161 static ssize_t
show_val_norm(int id
,struct class_device
*class_dev
,char *buf
)
163 struct pvr2_ctrl
*cptr
;
164 struct pvr2_sysfs
*sfp
;
166 unsigned int cnt
= 0;
168 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
169 if (!sfp
) return -EINVAL
;
170 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
171 if (!cptr
) return -EINVAL
;
173 ret
= pvr2_ctrl_get_value(cptr
,&val
);
174 if (ret
< 0) return ret
;
176 ret
= pvr2_ctrl_value_to_sym(cptr
,~0,val
,
177 buf
,PAGE_SIZE
-1,&cnt
);
179 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
185 static ssize_t
show_val_custom(int id
,struct class_device
*class_dev
,char *buf
)
187 struct pvr2_ctrl
*cptr
;
188 struct pvr2_sysfs
*sfp
;
190 unsigned int cnt
= 0;
192 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
193 if (!sfp
) return -EINVAL
;
194 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
195 if (!cptr
) return -EINVAL
;
197 ret
= pvr2_ctrl_get_value(cptr
,&val
);
198 if (ret
< 0) return ret
;
200 ret
= pvr2_ctrl_custom_value_to_sym(cptr
,~0,val
,
201 buf
,PAGE_SIZE
-1,&cnt
);
203 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
209 static ssize_t
show_enum(int id
,struct class_device
*class_dev
,char *buf
)
211 struct pvr2_ctrl
*cptr
;
212 struct pvr2_sysfs
*sfp
;
214 unsigned int bcnt
,ccnt
,ecnt
;
216 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
217 if (!sfp
) return -EINVAL
;
218 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
219 if (!cptr
) return -EINVAL
;
220 ecnt
= pvr2_ctrl_get_cnt(cptr
);
222 for (val
= 0; val
< ecnt
; val
++) {
223 pvr2_ctrl_get_valname(cptr
,val
,buf
+bcnt
,PAGE_SIZE
-bcnt
,&ccnt
);
226 if (bcnt
>= PAGE_SIZE
) break;
230 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp
,id
);
234 static ssize_t
show_bits(int id
,struct class_device
*class_dev
,char *buf
)
236 struct pvr2_ctrl
*cptr
;
237 struct pvr2_sysfs
*sfp
;
239 unsigned int bcnt
,ccnt
;
241 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
242 if (!sfp
) return -EINVAL
;
243 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
244 if (!cptr
) return -EINVAL
;
245 valid_bits
= pvr2_ctrl_get_mask(cptr
);
247 for (msk
= 1; valid_bits
; msk
<<= 1) {
248 if (!(msk
& valid_bits
)) continue;
250 pvr2_ctrl_get_valname(cptr
,msk
,buf
+bcnt
,PAGE_SIZE
-bcnt
,&ccnt
);
252 if (bcnt
>= PAGE_SIZE
) break;
256 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp
,id
);
260 static int store_val_any(int id
,int customfl
,struct pvr2_sysfs
*sfp
,
261 const char *buf
,unsigned int count
)
263 struct pvr2_ctrl
*cptr
;
267 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,id
);
269 ret
= pvr2_ctrl_custom_sym_to_value(cptr
,buf
,count
,&mask
,&val
);
271 ret
= pvr2_ctrl_sym_to_value(cptr
,buf
,count
,&mask
,&val
);
273 if (ret
< 0) return ret
;
274 ret
= pvr2_ctrl_set_mask_value(cptr
,mask
,val
);
275 pvr2_hdw_commit_ctl(sfp
->channel
.hdw
);
279 static ssize_t
store_val_norm(int id
,struct class_device
*class_dev
,
280 const char *buf
,size_t count
)
282 struct pvr2_sysfs
*sfp
;
284 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
285 ret
= store_val_any(id
,0,sfp
,buf
,count
);
286 if (!ret
) ret
= count
;
290 static ssize_t
store_val_custom(int id
,struct class_device
*class_dev
,
291 const char *buf
,size_t count
)
293 struct pvr2_sysfs
*sfp
;
295 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
296 ret
= store_val_any(id
,1,sfp
,buf
,count
);
297 if (!ret
) ret
= count
;
302 Mike Isely <isely@pobox.com> 30-April-2005
304 This next batch of horrible preprocessor hackery is needed because the
305 kernel's class_device_attribute mechanism fails to pass the actual
306 attribute through to the show / store functions, which means we have no
307 way to package up any attribute-specific parameters, like for example the
308 control id. So we work around this brain-damage by encoding the control
309 id into the show / store functions themselves and pick the function based
310 on the control id we're setting up. These macros try to ease the pain.
314 #define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
315 static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \
316 { return sf_name(ctl_id,class_dev,buf); }
318 #define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
319 static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \
320 { return sf_name(ctl_id,class_dev,buf,count); }
322 #define CREATE_BATCH(ctl_id) \
323 CREATE_SHOW_INSTANCE(show_name,ctl_id) \
324 CREATE_SHOW_INSTANCE(show_type,ctl_id) \
325 CREATE_SHOW_INSTANCE(show_min,ctl_id) \
326 CREATE_SHOW_INSTANCE(show_max,ctl_id) \
327 CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
328 CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
329 CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
330 CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
331 CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
332 CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
395 struct pvr2_sysfs_func_set
{
396 ssize_t (*show_name
)(struct class_device
*,char *);
397 ssize_t (*show_type
)(struct class_device
*,char *);
398 ssize_t (*show_min
)(struct class_device
*,char *);
399 ssize_t (*show_max
)(struct class_device
*,char *);
400 ssize_t (*show_enum
)(struct class_device
*,char *);
401 ssize_t (*show_bits
)(struct class_device
*,char *);
402 ssize_t (*show_val_norm
)(struct class_device
*,char *);
403 ssize_t (*store_val_norm
)(struct class_device
*,
404 const char *,size_t);
405 ssize_t (*show_val_custom
)(struct class_device
*,char *);
406 ssize_t (*store_val_custom
)(struct class_device
*,
407 const char *,size_t);
410 #define INIT_BATCH(ctl_id) \
412 .show_name = show_name_##ctl_id, \
413 .show_type = show_type_##ctl_id, \
414 .show_min = show_min_##ctl_id, \
415 .show_max = show_max_##ctl_id, \
416 .show_enum = show_enum_##ctl_id, \
417 .show_bits = show_bits_##ctl_id, \
418 .show_val_norm = show_val_norm_##ctl_id, \
419 .store_val_norm = store_val_norm_##ctl_id, \
420 .show_val_custom = show_val_custom_##ctl_id, \
421 .store_val_custom = store_val_custom_##ctl_id, \
424 static struct pvr2_sysfs_func_set funcs[] = {
488 static void pvr2_sysfs_add_control(struct pvr2_sysfs
*sfp
,int ctl_id
)
490 struct pvr2_sysfs_ctl_item
*cip
;
491 struct pvr2_sysfs_func_set
*fp
;
492 struct pvr2_ctrl
*cptr
;
493 unsigned int cnt
,acnt
;
496 if ((ctl_id
< 0) || (ctl_id
>= ARRAY_SIZE(funcs
))) {
501 cptr
= pvr2_hdw_get_ctrl_by_index(sfp
->channel
.hdw
,ctl_id
);
504 cip
= kzalloc(sizeof(*cip
),GFP_KERNEL
);
506 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip
);
511 cip
->item_next
= NULL
;
512 if (sfp
->item_last
) {
513 sfp
->item_last
->item_next
= cip
;
515 sfp
->item_first
= cip
;
517 sfp
->item_last
= cip
;
519 cip
->attr_name
.attr
.owner
= THIS_MODULE
;
520 cip
->attr_name
.attr
.name
= "name";
521 cip
->attr_name
.attr
.mode
= S_IRUGO
;
522 cip
->attr_name
.show
= fp
->show_name
;
524 cip
->attr_type
.attr
.owner
= THIS_MODULE
;
525 cip
->attr_type
.attr
.name
= "type";
526 cip
->attr_type
.attr
.mode
= S_IRUGO
;
527 cip
->attr_type
.show
= fp
->show_type
;
529 cip
->attr_min
.attr
.owner
= THIS_MODULE
;
530 cip
->attr_min
.attr
.name
= "min_val";
531 cip
->attr_min
.attr
.mode
= S_IRUGO
;
532 cip
->attr_min
.show
= fp
->show_min
;
534 cip
->attr_max
.attr
.owner
= THIS_MODULE
;
535 cip
->attr_max
.attr
.name
= "max_val";
536 cip
->attr_max
.attr
.mode
= S_IRUGO
;
537 cip
->attr_max
.show
= fp
->show_max
;
539 cip
->attr_val
.attr
.owner
= THIS_MODULE
;
540 cip
->attr_val
.attr
.name
= "cur_val";
541 cip
->attr_val
.attr
.mode
= S_IRUGO
;
543 cip
->attr_custom
.attr
.owner
= THIS_MODULE
;
544 cip
->attr_custom
.attr
.name
= "custom_val";
545 cip
->attr_custom
.attr
.mode
= S_IRUGO
;
547 cip
->attr_enum
.attr
.owner
= THIS_MODULE
;
548 cip
->attr_enum
.attr
.name
= "enum_val";
549 cip
->attr_enum
.attr
.mode
= S_IRUGO
;
550 cip
->attr_enum
.show
= fp
->show_enum
;
552 cip
->attr_bits
.attr
.owner
= THIS_MODULE
;
553 cip
->attr_bits
.attr
.name
= "bit_val";
554 cip
->attr_bits
.attr
.mode
= S_IRUGO
;
555 cip
->attr_bits
.show
= fp
->show_bits
;
557 if (pvr2_ctrl_is_writable(cptr
)) {
558 cip
->attr_val
.attr
.mode
|= S_IWUSR
|S_IWGRP
;
559 cip
->attr_custom
.attr
.mode
|= S_IWUSR
|S_IWGRP
;
563 cip
->attr_gen
[acnt
++] = &cip
->attr_name
.attr
;
564 cip
->attr_gen
[acnt
++] = &cip
->attr_type
.attr
;
565 cip
->attr_gen
[acnt
++] = &cip
->attr_val
.attr
;
566 cip
->attr_val
.show
= fp
->show_val_norm
;
567 cip
->attr_val
.store
= fp
->store_val_norm
;
568 if (pvr2_ctrl_has_custom_symbols(cptr
)) {
569 cip
->attr_gen
[acnt
++] = &cip
->attr_custom
.attr
;
570 cip
->attr_custom
.show
= fp
->show_val_custom
;
571 cip
->attr_custom
.store
= fp
->store_val_custom
;
573 switch (pvr2_ctrl_get_type(cptr
)) {
575 // Control is an enumeration
576 cip
->attr_gen
[acnt
++] = &cip
->attr_enum
.attr
;
579 // Control is an integer
580 cip
->attr_gen
[acnt
++] = &cip
->attr_min
.attr
;
581 cip
->attr_gen
[acnt
++] = &cip
->attr_max
.attr
;
583 case pvr2_ctl_bitmask
:
584 // Control is an bitmask
585 cip
->attr_gen
[acnt
++] = &cip
->attr_bits
.attr
;
590 cnt
= scnprintf(cip
->name
,sizeof(cip
->name
)-1,"ctl_%s",
591 pvr2_ctrl_get_name(cptr
));
593 cip
->grp
.name
= cip
->name
;
594 cip
->grp
.attrs
= cip
->attr_gen
;
596 ret
= sysfs_create_group(&sfp
->class_dev
->kobj
,&cip
->grp
);
598 printk(KERN_WARNING
"%s: sysfs_create_group error: %d\n",
602 cip
->created_ok
= !0;
605 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
606 static ssize_t
debuginfo_show(struct class_device
*,char *);
607 static ssize_t
debugcmd_show(struct class_device
*,char *);
608 static ssize_t
debugcmd_store(struct class_device
*,const char *,size_t count
);
610 static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs
*sfp
)
612 struct pvr2_sysfs_debugifc
*dip
;
615 dip
= kzalloc(sizeof(*dip
),GFP_KERNEL
);
617 dip
->attr_debugcmd
.attr
.owner
= THIS_MODULE
;
618 dip
->attr_debugcmd
.attr
.name
= "debugcmd";
619 dip
->attr_debugcmd
.attr
.mode
= S_IRUGO
|S_IWUSR
|S_IWGRP
;
620 dip
->attr_debugcmd
.show
= debugcmd_show
;
621 dip
->attr_debugcmd
.store
= debugcmd_store
;
622 dip
->attr_debuginfo
.attr
.owner
= THIS_MODULE
;
623 dip
->attr_debuginfo
.attr
.name
= "debuginfo";
624 dip
->attr_debuginfo
.attr
.mode
= S_IRUGO
;
625 dip
->attr_debuginfo
.show
= debuginfo_show
;
627 ret
= class_device_create_file(sfp
->class_dev
,&dip
->attr_debugcmd
);
629 printk(KERN_WARNING
"%s: class_device_create_file error: %d\n",
632 dip
->debugcmd_created_ok
= !0;
634 ret
= class_device_create_file(sfp
->class_dev
,&dip
->attr_debuginfo
);
636 printk(KERN_WARNING
"%s: class_device_create_file error: %d\n",
639 dip
->debuginfo_created_ok
= !0;
644 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs
*sfp
)
646 if (!sfp
->debugifc
) return;
647 if (sfp
->debugifc
->debuginfo_created_ok
) {
648 class_device_remove_file(sfp
->class_dev
,
649 &sfp
->debugifc
->attr_debuginfo
);
651 if (sfp
->debugifc
->debugcmd_created_ok
) {
652 class_device_remove_file(sfp
->class_dev
,
653 &sfp
->debugifc
->attr_debugcmd
);
655 kfree(sfp
->debugifc
);
656 sfp
->debugifc
= NULL
;
658 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
661 static void pvr2_sysfs_add_controls(struct pvr2_sysfs
*sfp
)
663 unsigned int idx
,cnt
;
664 cnt
= pvr2_hdw_get_ctrl_count(sfp
->channel
.hdw
);
665 for (idx
= 0; idx
< cnt
; idx
++) {
666 pvr2_sysfs_add_control(sfp
,idx
);
671 static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs
*sfp
)
673 struct pvr2_sysfs_ctl_item
*cip1
,*cip2
;
674 for (cip1
= sfp
->item_first
; cip1
; cip1
= cip2
) {
675 cip2
= cip1
->item_next
;
676 if (cip1
->created_ok
) {
677 sysfs_remove_group(&sfp
->class_dev
->kobj
,&cip1
->grp
);
679 pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1
);
685 static void pvr2_sysfs_class_release(struct class *class)
687 struct pvr2_sysfs_class
*clp
;
688 clp
= container_of(class,struct pvr2_sysfs_class
,class);
689 pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp
);
694 static void pvr2_sysfs_release(struct class_device
*class_dev
)
696 pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev
);
701 static void class_dev_destroy(struct pvr2_sysfs
*sfp
)
703 if (!sfp
->class_dev
) return;
704 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
705 pvr2_sysfs_tear_down_debugifc(sfp
);
706 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
707 pvr2_sysfs_tear_down_controls(sfp
);
708 if (sfp
->v4l_minor_number_created_ok
) {
709 class_device_remove_file(sfp
->class_dev
,
710 &sfp
->attr_v4l_minor_number
);
712 if (sfp
->v4l_radio_minor_number_created_ok
) {
713 class_device_remove_file(sfp
->class_dev
,
714 &sfp
->attr_v4l_radio_minor_number
);
716 if (sfp
->unit_number_created_ok
) {
717 class_device_remove_file(sfp
->class_dev
,
718 &sfp
->attr_unit_number
);
720 pvr2_sysfs_trace("Destroying class_dev id=%p",sfp
->class_dev
);
721 sfp
->class_dev
->class_data
= NULL
;
722 class_device_unregister(sfp
->class_dev
);
723 sfp
->class_dev
= NULL
;
727 static ssize_t
v4l_minor_number_show(struct class_device
*class_dev
,char *buf
)
729 struct pvr2_sysfs
*sfp
;
730 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
731 if (!sfp
) return -EINVAL
;
732 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
733 pvr2_hdw_v4l_get_minor_number(sfp
->channel
.hdw
,
734 pvr2_v4l_type_video
));
738 static ssize_t
v4l_radio_minor_number_show(struct class_device
*class_dev
,
741 struct pvr2_sysfs
*sfp
;
742 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
743 if (!sfp
) return -EINVAL
;
744 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
745 pvr2_hdw_v4l_get_minor_number(sfp
->channel
.hdw
,
746 pvr2_v4l_type_radio
));
750 static ssize_t
unit_number_show(struct class_device
*class_dev
,char *buf
)
752 struct pvr2_sysfs
*sfp
;
753 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
754 if (!sfp
) return -EINVAL
;
755 return scnprintf(buf
,PAGE_SIZE
,"%d\n",
756 pvr2_hdw_get_unit_number(sfp
->channel
.hdw
));
760 static void class_dev_create(struct pvr2_sysfs
*sfp
,
761 struct pvr2_sysfs_class
*class_ptr
)
763 struct usb_device
*usb_dev
;
764 struct class_device
*class_dev
;
767 usb_dev
= pvr2_hdw_get_dev(sfp
->channel
.hdw
);
768 if (!usb_dev
) return;
769 class_dev
= kzalloc(sizeof(*class_dev
),GFP_KERNEL
);
770 if (!class_dev
) return;
772 pvr2_sysfs_trace("Creating class_dev id=%p",class_dev
);
774 class_dev
->class = &class_ptr
->class;
775 if (pvr2_hdw_get_sn(sfp
->channel
.hdw
)) {
776 snprintf(class_dev
->class_id
,BUS_ID_SIZE
,"sn-%lu",
777 pvr2_hdw_get_sn(sfp
->channel
.hdw
));
778 } else if (pvr2_hdw_get_unit_number(sfp
->channel
.hdw
) >= 0) {
779 snprintf(class_dev
->class_id
,BUS_ID_SIZE
,"unit-%c",
780 pvr2_hdw_get_unit_number(sfp
->channel
.hdw
) + 'a');
786 class_dev
->dev
= &usb_dev
->dev
;
788 sfp
->class_dev
= class_dev
;
789 class_dev
->class_data
= sfp
;
790 ret
= class_device_register(class_dev
);
792 printk(KERN_ERR
"%s: class_device_register failed\n",
798 sfp
->attr_v4l_minor_number
.attr
.owner
= THIS_MODULE
;
799 sfp
->attr_v4l_minor_number
.attr
.name
= "v4l_minor_number";
800 sfp
->attr_v4l_minor_number
.attr
.mode
= S_IRUGO
;
801 sfp
->attr_v4l_minor_number
.show
= v4l_minor_number_show
;
802 sfp
->attr_v4l_minor_number
.store
= NULL
;
803 ret
= class_device_create_file(sfp
->class_dev
,
804 &sfp
->attr_v4l_minor_number
);
806 printk(KERN_WARNING
"%s: class_device_create_file error: %d\n",
809 sfp
->v4l_minor_number_created_ok
= !0;
812 sfp
->attr_v4l_radio_minor_number
.attr
.owner
= THIS_MODULE
;
813 sfp
->attr_v4l_radio_minor_number
.attr
.name
= "v4l_radio_minor_number";
814 sfp
->attr_v4l_radio_minor_number
.attr
.mode
= S_IRUGO
;
815 sfp
->attr_v4l_radio_minor_number
.show
= v4l_radio_minor_number_show
;
816 sfp
->attr_v4l_radio_minor_number
.store
= NULL
;
817 ret
= class_device_create_file(sfp
->class_dev
,
818 &sfp
->attr_v4l_radio_minor_number
);
820 printk(KERN_WARNING
"%s: class_device_create_file error: %d\n",
823 sfp
->v4l_radio_minor_number_created_ok
= !0;
826 sfp
->attr_unit_number
.attr
.owner
= THIS_MODULE
;
827 sfp
->attr_unit_number
.attr
.name
= "unit_number";
828 sfp
->attr_unit_number
.attr
.mode
= S_IRUGO
;
829 sfp
->attr_unit_number
.show
= unit_number_show
;
830 sfp
->attr_unit_number
.store
= NULL
;
831 ret
= class_device_create_file(sfp
->class_dev
,&sfp
->attr_unit_number
);
833 printk(KERN_WARNING
"%s: class_device_create_file error: %d\n",
836 sfp
->unit_number_created_ok
= !0;
839 pvr2_sysfs_add_controls(sfp
);
840 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
841 pvr2_sysfs_add_debugifc(sfp
);
842 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
846 static void pvr2_sysfs_internal_check(struct pvr2_channel
*chp
)
848 struct pvr2_sysfs
*sfp
;
849 sfp
= container_of(chp
,struct pvr2_sysfs
,channel
);
850 if (!sfp
->channel
.mc_head
->disconnect_flag
) return;
851 pvr2_trace(PVR2_TRACE_STRUCT
,"Destroying pvr2_sysfs id=%p",sfp
);
852 class_dev_destroy(sfp
);
853 pvr2_channel_done(&sfp
->channel
);
858 struct pvr2_sysfs
*pvr2_sysfs_create(struct pvr2_context
*mp
,
859 struct pvr2_sysfs_class
*class_ptr
)
861 struct pvr2_sysfs
*sfp
;
862 sfp
= kzalloc(sizeof(*sfp
),GFP_KERNEL
);
863 if (!sfp
) return sfp
;
864 pvr2_trace(PVR2_TRACE_STRUCT
,"Creating pvr2_sysfs id=%p",sfp
);
865 pvr2_channel_init(&sfp
->channel
,mp
);
866 sfp
->channel
.check_func
= pvr2_sysfs_internal_check
;
868 class_dev_create(sfp
,class_ptr
);
873 static int pvr2_sysfs_hotplug(struct class_device
*cd
,char **envp
,
874 int numenvp
,char *buf
,int size
)
876 /* Even though we don't do anything here, we still need this function
877 because sysfs will still try to call it. */
881 struct pvr2_sysfs_class
*pvr2_sysfs_class_create(void)
883 struct pvr2_sysfs_class
*clp
;
884 clp
= kzalloc(sizeof(*clp
),GFP_KERNEL
);
885 if (!clp
) return clp
;
886 pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp
);
887 clp
->class.name
= "pvrusb2";
888 clp
->class.class_release
= pvr2_sysfs_class_release
;
889 clp
->class.release
= pvr2_sysfs_release
;
890 clp
->class.uevent
= pvr2_sysfs_hotplug
;
891 if (class_register(&clp
->class)) {
893 "Registration failed for pvr2_sysfs_class id=%p",clp
);
901 void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class
*clp
)
903 class_unregister(&clp
->class);
907 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
908 static ssize_t
debuginfo_show(struct class_device
*class_dev
,char *buf
)
910 struct pvr2_sysfs
*sfp
;
911 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
912 if (!sfp
) return -EINVAL
;
913 pvr2_hdw_trigger_module_log(sfp
->channel
.hdw
);
914 return pvr2_debugifc_print_info(sfp
->channel
.hdw
,buf
,PAGE_SIZE
);
918 static ssize_t
debugcmd_show(struct class_device
*class_dev
,char *buf
)
920 struct pvr2_sysfs
*sfp
;
921 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
922 if (!sfp
) return -EINVAL
;
923 return pvr2_debugifc_print_status(sfp
->channel
.hdw
,buf
,PAGE_SIZE
);
927 static ssize_t
debugcmd_store(struct class_device
*class_dev
,
928 const char *buf
,size_t count
)
930 struct pvr2_sysfs
*sfp
;
933 sfp
= (struct pvr2_sysfs
*)class_dev
->class_data
;
934 if (!sfp
) return -EINVAL
;
936 ret
= pvr2_debugifc_docmd(sfp
->channel
.hdw
,buf
,count
);
937 if (ret
< 0) return ret
;
940 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
944 Stuff for Emacs to see, in order to encourage consistent editing style:
945 *** Local Variables: ***
947 *** fill-column: 75 ***
949 *** c-basic-offset: 8 ***